1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/*
2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification
3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *             of Java bytecode.
4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
59f606f95f03a75961498803e24bee6799a7c0885Ying Wang * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu)
6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it
8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free
9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option)
10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version.
11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT
13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details.
16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along
18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc.,
19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard.evaluation;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.evaluation.value.Value;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This Variables class saves additional information with variables, to keep
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * track of their origins.
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * <p>
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * The Variables class stores a given producer Value along with each Value it
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * stores. It then generalizes a given collected Value with the producer Value
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of each Value it loads. The producer Value and the initial collected Value
32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * can be set; the generalized collected Value can be retrieved.
339f606f95f03a75961498803e24bee6799a7c0885Ying Wang * <p>
349f606f95f03a75961498803e24bee6799a7c0885Ying Wang * In addition, an initialization index can be reset and retrieved, pointing
359f606f95f03a75961498803e24bee6799a7c0885Ying Wang * to the most recent variable that has been initialized by a store operation.
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class TracedVariables extends Variables
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public static final int NONE = -1;
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private Value     producerValue;
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private Variables producerVariables;
469f606f95f03a75961498803e24bee6799a7c0885Ying Wang    private int       initializationIndex;
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new TracedVariables with a given size.
51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public TracedVariables(int size)
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        super(size);
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        producerVariables = new Variables(size);
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new TracedVariables that is a copy of the given TracedVariables.
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public TracedVariables(TracedVariables tracedVariables)
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        super(tracedVariables);
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        producerVariables = new Variables(tracedVariables.producerVariables);
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Sets the Value that will be stored along with all store instructions.
73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void setProducerValue(Value producerValue)
75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.producerValue = producerValue;
77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
819f606f95f03a75961498803e24bee6799a7c0885Ying Wang     * Resets the initialization index.
829f606f95f03a75961498803e24bee6799a7c0885Ying Wang     */
839f606f95f03a75961498803e24bee6799a7c0885Ying Wang    public void resetInitialization()
849f606f95f03a75961498803e24bee6799a7c0885Ying Wang    {
859f606f95f03a75961498803e24bee6799a7c0885Ying Wang        initializationIndex = NONE;
869f606f95f03a75961498803e24bee6799a7c0885Ying Wang    }
879f606f95f03a75961498803e24bee6799a7c0885Ying Wang
889f606f95f03a75961498803e24bee6799a7c0885Ying Wang
899f606f95f03a75961498803e24bee6799a7c0885Ying Wang    /**
909f606f95f03a75961498803e24bee6799a7c0885Ying Wang     * Returns the most recent initialization index since it has been reset.
919f606f95f03a75961498803e24bee6799a7c0885Ying Wang     */
929f606f95f03a75961498803e24bee6799a7c0885Ying Wang    public int getInitializationIndex()
939f606f95f03a75961498803e24bee6799a7c0885Ying Wang    {
949f606f95f03a75961498803e24bee6799a7c0885Ying Wang        return initializationIndex;
959f606f95f03a75961498803e24bee6799a7c0885Ying Wang    }
969f606f95f03a75961498803e24bee6799a7c0885Ying Wang
979f606f95f03a75961498803e24bee6799a7c0885Ying Wang
989f606f95f03a75961498803e24bee6799a7c0885Ying Wang    /**
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Gets the producer Value for the specified variable, without disturbing it.
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param index the variable index.
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @return the producer value of the given variable.
102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public Value getProducerValue(int index)
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return producerVariables.getValue(index);
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Sets the given producer Value for the specified variable, without
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * disturbing it.
112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param index the variable index.
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param value the producer value to set.
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void setProducerValue(int index, Value value)
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        producerVariables.store(index, value);
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for Variables.
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void reset(int size)
124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        super.reset(size);
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        producerVariables.reset(size);
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void initialize(TracedVariables other)
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        super.initialize(other);
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        producerVariables.initialize(other.producerVariables);
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public boolean generalize(TracedVariables other,
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                              boolean         clearConflictingOtherVariables)
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        boolean variablesChanged = super.generalize(other, clearConflictingOtherVariables);
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        boolean producersChanged = producerVariables.generalize(other.producerVariables, clearConflictingOtherVariables);
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        /* consumerVariables.generalize(other.consumerVariables)*/
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Clear any traces if a variable has become null.
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (variablesChanged)
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            for (int index = 0; index < size; index++)
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (values[index] == null)
150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    producerVariables.values[index] = null;
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    if (clearConflictingOtherVariables)
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    {
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        other.producerVariables.values[index] = null;
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    }
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return variablesChanged || producersChanged;
162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void store(int index, Value value)
166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
1679f606f95f03a75961498803e24bee6799a7c0885Ying Wang        // Is this store operation an initialization of the variable?
1689f606f95f03a75961498803e24bee6799a7c0885Ying Wang        Value previousValue = super.load(index);
1699f606f95f03a75961498803e24bee6799a7c0885Ying Wang        if (previousValue == null ||
1709f606f95f03a75961498803e24bee6799a7c0885Ying Wang            previousValue.computationalType() != value.computationalType())
1719f606f95f03a75961498803e24bee6799a7c0885Ying Wang        {
1729f606f95f03a75961498803e24bee6799a7c0885Ying Wang            initializationIndex = index;
1739f606f95f03a75961498803e24bee6799a7c0885Ying Wang        }
1749f606f95f03a75961498803e24bee6799a7c0885Ying Wang
175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Store the value itself in the variable.
176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        super.store(index, value);
177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Store the producer value in its producer variable.
179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        producerVariables.store(index, producerValue);
180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Account for the extra space required by Category 2 values.
182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (value.isCategory2())
183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            producerVariables.store(index+1, producerValue);
185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for Object.
190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public boolean equals(Object object)
192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (object == null ||
194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            this.getClass() != object.getClass())
195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            return false;
197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        TracedVariables other = (TracedVariables)object;
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return super.equals(object) &&
202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               this.producerVariables.equals(other.producerVariables);
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public int hashCode()
207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return super.hashCode() ^
209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               producerVariables.hashCode();
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public String toString()
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        StringBuffer buffer = new StringBuffer();
216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        for (int index = 0; index < this.size(); index++)
218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            Value value         = this.values[index];
220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            Value producerValue = producerVariables.getValue(index);
221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            buffer = buffer.append('[')
222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                           .append(producerValue == null ? "empty:" : producerValue.toString())
223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                           .append(value         == null ? "empty"  : value.toString())
224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                           .append(']');
225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return buffer.toString();
228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
230