1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/*
2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification
3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *             of Java bytecode.
4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
5b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Copyright (c) 2002-2013 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.optimize.info;
22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*;
24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.CodeAttribute;
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.*;
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.visitor.ConstantVisitor;
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.*;
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.visitor.InstructionVisitor;
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.SimplifiedVisitor;
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.visitor.*;
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
32b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport java.util.*;
33b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
35b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * This class can tell whether an instruction has any side effects outside of
36b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * its method. Return instructions can be included or not.
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see ReadWriteFieldMarker
39b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * @see StaticInitializerContainingClassMarker
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see NoSideEffectMethodMarker
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see SideEffectMethodMarker
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class SideEffectInstructionChecker
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends      SimplifiedVisitor
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements   InstructionVisitor,
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             ConstantVisitor,
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             MemberVisitor
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
50b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private static final boolean OPTIMIZE_CONSERVATIVELY = System.getProperty("optimize.conservatively") != null;
51b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
52b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final boolean includeReturnInstructions;
54b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private final boolean includeLocalFieldAccess;
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // A return value for the visitor methods.
57b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private Clazz   referencingClass;
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean hasSideEffects;
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
61b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public SideEffectInstructionChecker(boolean includeReturnInstructions,
62b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                        boolean includeLocalFieldAccess)
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.includeReturnInstructions = includeReturnInstructions;
65b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        this.includeLocalFieldAccess   = includeLocalFieldAccess;
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
69b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    /**
70b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Returns whether the given instruction has side effects outside of its
71b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * method.
72b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     */
73b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public boolean hasSideEffects(Clazz         clazz,
74b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                  Method        method,
75b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                  CodeAttribute codeAttribute,
76b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                  int           offset,
77b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                  Instruction   instruction)
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        hasSideEffects = false;
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
81b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        instruction.accept(clazz, method, codeAttribute, offset, this);
82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        return hasSideEffects;
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for InstructionVisitor.
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction) {}
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        byte opcode = simpleInstruction.opcode;
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Check for instructions that might cause side effects.
97b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        switch (opcode)
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
99b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_IALOAD:
100b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_LALOAD:
101b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_FALOAD:
102b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_DALOAD:
103b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_AALOAD:
104b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_BALOAD:
105b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_CALOAD:
106b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_SALOAD:
107b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // These instructions strictly taken may cause a side effect
108b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // (NullPointerException, ArrayIndexOutOfBoundsException).
109b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                hasSideEffects = OPTIMIZE_CONSERVATIVELY;
110b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                break;
111b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
112b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_IASTORE:
113b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_LASTORE:
114b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_FASTORE:
115b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_DASTORE:
116b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_AASTORE:
117b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_BASTORE:
118b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_CASTORE:
119b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_SASTORE:
120b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_ATHROW :
121b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_MONITORENTER:
122b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_MONITOREXIT:
123b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // These instructions always cause a side effect.
124b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                hasSideEffects = true;
125b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                break;
126b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
127b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_IRETURN:
128b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_LRETURN:
129b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_FRETURN:
130b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_DRETURN:
131b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_ARETURN:
132b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_RETURN:
133b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // These instructions may have a side effect.
134b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                hasSideEffects = includeReturnInstructions;
135b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                break;
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        byte opcode = variableInstruction.opcode;
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Check for instructions that might cause side effects.
145b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        switch (opcode)
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
147b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_RET:
148b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // This instruction may have a side effect.
149b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                hasSideEffects = includeReturnInstructions;
150b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                break;
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        byte opcode = constantInstruction.opcode;
1589f606f95f03a75961498803e24bee6799a7c0885Ying Wang
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Check for instructions that might cause side effects.
160b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        switch (opcode)
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
162b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_GETSTATIC:
163b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_PUTSTATIC:
164b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_INVOKESPECIAL:
165b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_INVOKESTATIC:
166b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // Check if the field is write-only or volatile, or if the
167b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // invoked method is causing any side effects.
168b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
169b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                break;
170b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
171b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_GETFIELD:
172b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_PUTFIELD:
173b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_INVOKEVIRTUAL:
174b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_INVOKEINTERFACE:
175b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_INVOKEDYNAMIC:
176b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                if (OPTIMIZE_CONSERVATIVELY)
177b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                {
178b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    // These instructions strictly taken may cause a side effect
179b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    // (NullPointerException).
180b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    hasSideEffects = true;
181b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                }
182b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                else
183b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                {
184b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    // Check if the field is write-only or volatile, or if the
185b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    // invoked method is causing any side effects.
186b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                    clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
187b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                }
188b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                break;
189b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
190b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_CHECKCAST:
191b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // This instructions strictly taken may cause a side effect
192b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                // (ClassCastException).
193b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                hasSideEffects = OPTIMIZE_CONSERVATIVELY;
194b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                break;
195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction)
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        byte opcode = branchInstruction.opcode;
202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Check for instructions that might cause side effects.
204b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        switch (opcode)
205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
206b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_JSR:
207b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            case InstructionConstants.OP_JSR_W:
208b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                hasSideEffects = includeReturnInstructions;
209b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                break;
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for ConstantVisitor.
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
216b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    public void visitInvokeDynamicConstant(Clazz clazz, InvokeDynamicConstant invokeDynamicConstant)
217b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
218b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // We'll have to assume invoking an unknown method has side effects.
219b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        hasSideEffects = true;
220b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
221b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
222b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitFieldrefConstant(Clazz clazz, FieldrefConstant fieldrefConstant)
224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
225b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Pass the referencing class.
226b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        referencingClass = clazz;
227b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // We'll have to assume accessing an unknown field has side effects.
229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        hasSideEffects = true;
230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
231b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Check the referenced field, if known.
232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        fieldrefConstant.referencedMemberAccept(this);
233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnyMethodrefConstant(Clazz clazz, RefConstant refConstant)
237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
238b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Pass the referencing class.
239b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        referencingClass = clazz;
240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
241b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // We'll have to assume invoking an unknown method has side effects.
242b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        hasSideEffects = true;
243b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
244b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Check the referenced method, if known.
245b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        refConstant.referencedMemberAccept(this);
246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for MemberVisitor.
250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitProgramField(ProgramClass programClass, ProgramField programField)
252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
253b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        hasSideEffects =
254b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            (includeLocalFieldAccess || !programClass.equals(referencingClass)) &&
255b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            ((ReadWriteFieldMarker.isRead(programField) &&
256b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang              ReadWriteFieldMarker.isWritten(programField))                                ||
257b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang             ((programField.getAccessFlags() & ClassConstants.INTERNAL_ACC_VOLATILE) != 0) ||
258b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang             (!programClass.equals(referencingClass) &&
259b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang              !initializedSuperClasses(referencingClass).containsAll(initializedSuperClasses(programClass))));
260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
265b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Note that side effects already include synchronization of some
266b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // implementation of the method.
267b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        hasSideEffects =
268b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            !NoSideEffectMethodMarker.hasNoSideEffects(programMethod) &&
269b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            (SideEffectMethodMarker.hasSideEffects(programMethod) ||
270b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang             (!programClass.equals(referencingClass) &&
271b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang              !initializedSuperClasses(referencingClass).containsAll(initializedSuperClasses(programClass))));
272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitLibraryField(LibraryClass libraryClass, LibraryField libraryField)
276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        hasSideEffects = true;
278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitLibraryMethod(LibraryClass libraryClass, LibraryMethod libraryMethod)
282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
283b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        hasSideEffects =
284b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang            !NoSideEffectMethodMarker.hasNoSideEffects(libraryMethod);
285b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    }
286b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
287b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
288b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    /**
289b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     * Returns the set of superclasses and interfaces that are initialized.
290b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang     */
291b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    private Set initializedSuperClasses(Clazz clazz)
292b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang    {
293b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        Set set = new HashSet();
294b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
295b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // Visit all superclasses and interfaces, collecting the ones that have
296b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        // static initializers.
297b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        clazz.hierarchyAccept(true, true, true, false,
298b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                              new StaticInitializerContainingClassFilter(
299b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                              new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
300b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                                                     ClassConstants.INTERNAL_METHOD_TYPE_CLINIT,
301b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                              new SideEffectMethodFilter(
302b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                              new MemberToClassVisitor(
303b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang                              new ClassCollector(set))))));
304b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang
305b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang        return set;
306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
308