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