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.optimize.evaluation;
22
23import proguard.classfile.*;
24import proguard.classfile.constant.RefConstant;
25import proguard.evaluation.BasicInvocationUnit;
26import proguard.evaluation.value.*;
27import proguard.optimize.info.*;
28
29/**
30 * This InvocationUbit stores parameter values and return values with the
31 * methods that are invoked.
32 *
33 * @see LoadingInvocationUnit
34 * @author Eric Lafortune
35 */
36public class StoringInvocationUnit
37extends      BasicInvocationUnit
38{
39    private boolean storeFieldValues;
40    private boolean storeMethodParameterValues;
41    private boolean storeMethodReturnValues;
42
43
44    /**
45     * Creates a new StoringInvocationUnit with the given value factory.
46     */
47    public StoringInvocationUnit(ValueFactory valueFactory)
48    {
49        this(valueFactory, true, true, true);
50    }
51
52
53    /**
54     * Creates a new StoringInvocationUnit with the given value factory, for
55     * storing the specified values.
56     */
57    public StoringInvocationUnit(ValueFactory valueFactory,
58                                 boolean      storeFieldValues,
59                                 boolean      storeMethodParameterValues,
60                                 boolean      storeMethodReturnValues)
61    {
62        super(valueFactory);
63
64        this.storeFieldValues           = storeFieldValues;
65        this.storeMethodParameterValues = storeMethodParameterValues;
66        this.storeMethodReturnValues    = storeMethodReturnValues;
67    }
68
69
70    // Implementations for BasicInvocationUnit.
71
72    protected void setFieldClassValue(Clazz          clazz,
73                                      RefConstant    refConstant,
74                                      ReferenceValue value)
75    {
76        if (storeFieldValues)
77        {
78            Member referencedMember = refConstant.referencedMember;
79            if (referencedMember != null)
80            {
81                generalizeFieldClassValue((Field)referencedMember, value);
82            }
83        }
84    }
85
86
87    protected void setFieldValue(Clazz       clazz,
88                                 RefConstant refConstant,
89                                 Value       value)
90    {
91        if (storeFieldValues)
92        {
93            Member referencedMember = refConstant.referencedMember;
94            if (referencedMember != null)
95            {
96                generalizeFieldValue((Field)referencedMember, value);
97            }
98        }
99    }
100
101
102    protected void setMethodParameterValue(Clazz       clazz,
103                                           RefConstant refConstant,
104                                           int         parameterIndex,
105                                           Value       value)
106    {
107        if (storeMethodParameterValues)
108        {
109            Member referencedMember = refConstant.referencedMember;
110            if (referencedMember != null)
111            {
112                generalizeMethodParameterValue((Method)referencedMember,
113                                               parameterIndex,
114                                               value);
115            }
116        }
117    }
118
119
120    protected void setMethodReturnValue(Clazz  clazz,
121                                        Method method,
122                                        Value  value)
123    {
124        if (storeMethodReturnValues)
125        {
126            generalizeMethodReturnValue(method, value);
127        }
128    }
129
130
131    // Small utility methods.
132
133    private static void generalizeFieldClassValue(Field field, ReferenceValue value)
134    {
135        FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
136        if (info != null)
137        {
138            info.generalizeReferencedClass(value);
139        }
140    }
141
142
143    public static ReferenceValue getFieldClassValue(Field field)
144    {
145        FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
146        return info != null ?
147            info.getReferencedClass() :
148            null;
149    }
150
151
152    private static void generalizeFieldValue(Field field, Value value)
153    {
154        FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
155        if (info != null)
156        {
157            info.generalizeValue(value);
158        }
159    }
160
161
162    public static Value getFieldValue(Field field)
163    {
164        FieldOptimizationInfo info = FieldOptimizationInfo.getFieldOptimizationInfo(field);
165        return info != null ?
166            info.getValue() :
167            null;
168    }
169
170
171    private static void generalizeMethodParameterValue(Method method, int parameterIndex, Value value)
172    {
173        MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
174        if (info != null)
175        {
176            info.generalizeParameter(parameterIndex, value);
177        }
178    }
179
180
181    public static Value getMethodParameterValue(Method method, int parameterIndex)
182    {
183        MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
184        return info != null ?
185            info.getParameter(parameterIndex) :
186            null;
187    }
188
189
190    private static void generalizeMethodReturnValue(Method method, Value value)
191    {
192        MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
193        if (info != null)
194        {
195            info.generalizeReturnValue(value);
196        }
197    }
198
199
200    public static Value getMethodReturnValue(Method method)
201    {
202        MethodOptimizationInfo info = MethodOptimizationInfo.getMethodOptimizationInfo(method);
203        return info != null ?
204            info.getReturnValue() :
205            null;
206    }
207}
208