1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/* 2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification 3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of Java bytecode. 4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 52270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Copyright (c) 2002-2014 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.peephole; 22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*; 24b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wangimport proguard.classfile.attribute.visitor.AttributeNameFilter; 25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.visitor.*; 26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.editor.*; 27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.*; 28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.visitor.*; 29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.optimize.KeepMarker; 30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.optimize.info.*; 31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.util.*; 32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.util.*; 34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/** 36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This ClassVisitor inlines the classes that it visits in a given target class, 37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * whenever possible. 38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see RetargetedInnerClassAttributeRemover 40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see TargetClassChanger 41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see ClassReferenceFixer 42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see MemberReferenceFixer 43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see AccessFixer 44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune 45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class ClassMerger 47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends SimplifiedVisitor 48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements ClassVisitor, 49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ConstantVisitor 50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{ 51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //* 522270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private static final boolean DEBUG = false; 532270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private static final boolean DETAILS = false; 54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /*/ 552270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private static boolean DEBUG = System.getProperty("cm") != null; 562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private static boolean DETAILS = System.getProperty("cmd") != null; 57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //*/ 58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final ProgramClass targetClass; 61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final boolean allowAccessModification; 62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final boolean mergeInterfacesAggressively; 63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final ClassVisitor extraClassVisitor; 64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 65b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private final MemberVisitor fieldOptimizationInfoCopier = new FieldOptimizationInfoCopier(); 66b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Creates a new ClassMerger that will merge classes into the given target 70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * class. 71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param targetClass the class into which all visited 72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * classes will be merged. 73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param allowAccessModification specifies whether the access modifiers 74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of classes can be changed in order to 75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * merge them. 76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param mergeInterfacesAggressively specifies whether interfaces may 77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * be merged aggressively. 78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public ClassMerger(ProgramClass targetClass, 80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato boolean allowAccessModification, 81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato boolean mergeInterfacesAggressively) 82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this(targetClass, allowAccessModification, mergeInterfacesAggressively, null); 84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Creates a new ClassMerger that will merge classes into the given target 89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * class. 90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param targetClass the class into which all visited 91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * classes will be merged. 92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param allowAccessModification specifies whether the access modifiers 93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of classes can be changed in order to 94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * merge them. 95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param mergeInterfacesAggressively specifies whether interfaces may 96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * be merged aggressively. 97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param extraClassVisitor an optional extra visitor for all 98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * merged classes. 99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public ClassMerger(ProgramClass targetClass, 101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato boolean allowAccessModification, 102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato boolean mergeInterfacesAggressively, 103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassVisitor extraClassVisitor) 104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.targetClass = targetClass; 106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.allowAccessModification = allowAccessModification; 107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.mergeInterfacesAggressively = mergeInterfacesAggressively; 108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.extraClassVisitor = extraClassVisitor; 109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for ClassVisitor. 113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitProgramClass(ProgramClass programClass) 115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //final String CLASS_NAME = "abc/Def"; 117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //DEBUG = programClass.getName().equals(CLASS_NAME) || 118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // targetClass.getName().equals(CLASS_NAME); 119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // TODO: Remove this when the class merger has stabilized. 121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Catch any unexpected exceptions from the actual visiting method. 122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato try 123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato visitProgramClass0(programClass); 125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato catch (RuntimeException ex) 127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println("Unexpected error while merging classes:"); 129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println(" Class = ["+programClass.getName()+"]"); 130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println(" Target class = ["+targetClass.getName()+"]"); 131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")"); 132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) 134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.accept(new ClassPrinter()); 136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato targetClass.accept(new ClassPrinter()); 137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw ex; 140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitProgramClass0(ProgramClass programClass) 144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (!programClass.equals(targetClass) && 146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Don't merge classes that must be preserved. 148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !KeepMarker.isKept(programClass) && 149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !KeepMarker.isKept(targetClass) && 150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Only merge classes that haven't been retargeted yet. 152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato getTargetClass(programClass) == null && 153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato getTargetClass(targetClass) == null && 154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Don't merge annotation classes, with all their introspection and 156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // infinite recursion. 1572270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (programClass.getAccessFlags() & ClassConstants.ACC_ANNOTATTION) == 0 && 1582270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1592270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "Package visibility?")) && 160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 161b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Only merge classes if we can change the access permissions, or 162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // if they are in the same package, or 163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // if they are public and don't contain or invoke package visible 164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // class members. 165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (allowAccessModification || 166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ((programClass.getAccessFlags() & 167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato targetClass.getAccessFlags() & 1682270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ClassConstants.ACC_PUBLIC) != 0 && 169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !PackageVisibleMemberContainingClassMarker.containsPackageVisibleMembers(programClass) && 170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !PackageVisibleMemberInvokingClassMarker.invokesPackageVisibleMembers(programClass)) || 171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassUtil.internalPackageName(programClass.getName()).equals( 172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassUtil.internalPackageName(targetClass.getName()))) && 173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "Interface/abstract/single?")) && 1752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Only merge two classes or two interfaces or two abstract classes, 1772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // or a single implementation into its interface. 178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ((programClass.getAccessFlags() & 1792270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (ClassConstants.ACC_INTERFACE | 1802270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ClassConstants.ACC_ABSTRACT)) == 181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (targetClass.getAccessFlags() & 1822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (ClassConstants.ACC_INTERFACE | 1832270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ClassConstants.ACC_ABSTRACT)) || 184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (isOnlySubClass(programClass, targetClass) && 1852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom programClass.getSuperClass() != null && 186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (programClass.getSuperClass().equals(targetClass) || 187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.getSuperClass().equals(targetClass.getSuperClass())))) && 188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "Indirect implementation?")) && 1902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // One class must not implement the other class indirectly. 192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !indirectlyImplementedInterfaces(programClass).contains(targetClass) && 193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !targetClass.extendsOrImplements(programClass) && 194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "Interfaces same subinterfaces?")) && 1962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 1972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Interfaces must have exactly the same subinterfaces, not 1982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // counting themselves, to avoid any loops in the interface 1992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // hierarchy. 2002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ((programClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) == 0 || 2012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (targetClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) == 0 || 2022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom subInterfaces(programClass, targetClass).equals(subInterfaces(targetClass, programClass))) && 2032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 2042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "Same initialized superclasses?")) && 2052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The two classes must have the same superclasses and interfaces 207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // with static initializers. 208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato initializedSuperClasses(programClass).equals(initializedSuperClasses(targetClass)) && 209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 2102270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "Same instanceofed superclasses?")) && 2112270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The two classes must have the same superclasses and interfaces 213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // that are tested with 'instanceof'. 214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instanceofedSuperClasses(programClass).equals(instanceofedSuperClasses(targetClass)) && 215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 2162270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "Same caught superclasses?")) && 2172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The two classes must have the same superclasses that are caught 219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // as exceptions. 220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato caughtSuperClasses(programClass).equals(caughtSuperClasses(targetClass)) && 221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 2222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "Not .classed?")) && 2232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The two classes must not both be part of a .class construct. 225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !(DotClassMarker.isDotClassed(programClass) && 226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato DotClassMarker.isDotClassed(targetClass)) && 227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 2282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "No clashing fields?")) && 2292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 230b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // The classes must not have clashing fields. 231b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang !haveAnyIdenticalFields(programClass, targetClass) && 232b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 2332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "No unwanted fields?")) && 2342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The two classes must not introduce any unwanted fields. 236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !introducesUnwantedFields(programClass, targetClass) && 237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !introducesUnwantedFields(targetClass, programClass) && 238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 2392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "No shadowed fields?")) && 2402270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 241b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // The two classes must not shadow each others fields. 242b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang !shadowsAnyFields(programClass, targetClass) && 243b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang !shadowsAnyFields(targetClass, programClass) && 244b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 2452270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "No clashing methods?")) && 2462270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 247b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // The classes must not have clashing methods. 248b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang !haveAnyIdenticalMethods(programClass, targetClass) && 249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 2502270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "No abstract methods?")) && 2512270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The classes must not introduce abstract methods, unless 253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // explicitly allowed. 254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (mergeInterfacesAggressively || 255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (!introducesUnwantedAbstractMethods(programClass, targetClass) && 256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !introducesUnwantedAbstractMethods(targetClass, programClass))) && 257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 2582270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "No overridden methods?")) && 2592270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The classes must not override each others concrete methods. 261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !overridesAnyMethods(programClass, targetClass) && 262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !overridesAnyMethods(targetClass, programClass) && 263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 2642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (!DETAILS || print(programClass, "No shadowed methods?")) && 2652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The classes must not shadow each others non-private methods. 267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !shadowsAnyMethods(programClass, targetClass) && 268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !shadowsAnyMethods(targetClass, programClass)) 269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 2702270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // We're not actually merging the classes, but only copying the 2712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // contents from the source class to the target class. We'll 2722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // then let all other classes point to it. The shrinking step 2732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // will finally remove the source class. 274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) 275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println("ClassMerger ["+programClass.getName()+"] -> ["+targetClass.getName()+"]"); 2772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom System.out.println(" Source interface? ["+((programClass.getAccessFlags() & ClassConstants.ACC_INTERFACE)!=0)+"]"); 2782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom System.out.println(" Target interface? ["+((targetClass.getAccessFlags() & ClassConstants.ACC_INTERFACE)!=0)+"]"); 279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Source subclasses ["+programClass.subClasses+"]"); 280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Target subclasses ["+targetClass.subClasses+"]"); 281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Source superclass ["+programClass.getSuperClass().getName()+"]"); 282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Target superclass ["+targetClass.getSuperClass().getName()+"]"); 283b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 284b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang //System.out.println("=== Before ==="); 285b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang //programClass.accept(new ClassPrinter()); 286b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang //targetClass.accept(new ClassPrinter()); 287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Combine the access flags. 290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int targetAccessFlags = targetClass.getAccessFlags(); 291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int sourceAccessFlags = programClass.getAccessFlags(); 292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato targetClass.u2accessFlags = 294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ((targetAccessFlags & 295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato sourceAccessFlags) & 2962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (ClassConstants.ACC_INTERFACE | 2972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ClassConstants.ACC_ABSTRACT)) | 298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ((targetAccessFlags | 299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato sourceAccessFlags) & 3002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (ClassConstants.ACC_PUBLIC | 3012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ClassConstants.ACC_SUPER | 3022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ClassConstants.ACC_ANNOTATTION | 3032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ClassConstants.ACC_ENUM)); 3042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 3052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Copy over the superclass, if it's a non-interface class being 3062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // merged into an interface class. 3072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // However, we're currently never merging in a way that changes the 3082270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // superclass. 3092270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom //if ((programClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) == 0 && 3102270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // (targetClass.getAccessFlags() & ClassConstants.ACC_INTERFACE) != 0) 311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //{ 312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // targetClass.u2superClass = 313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // new ConstantAdder(targetClass).addConstant(programClass, programClass.u2superClass); 314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //} 315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Copy over the interfaces that aren't present yet and that 317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // wouldn't cause loops in the class hierarchy. 3182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Note that the code shouldn't be iterating over the original 3192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // list at this point. This is why we only add subclasses in 3202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // a separate step. 321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.interfaceConstantsAccept( 322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ExceptClassConstantFilter(targetClass.getName(), 323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ImplementedClassConstantFilter(targetClass, 324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ImplementingClassConstantFilter(targetClass, 325b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new InterfaceAdder(targetClass))))); 326b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 327b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Copy over the class members. 328b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato MemberAdder memberAdder = 329b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new MemberAdder(targetClass, fieldOptimizationInfoCopier); 330b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 331b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.fieldsAccept(memberAdder); 332b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.methodsAccept(memberAdder); 333b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 334b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Copy over the other attributes. 335b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.attributesAccept( 3362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new AttributeNameFilter(new NotMatcher( 3372270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new OrMatcher(new FixedStringMatcher(ClassConstants.ATTR_BootstrapMethods), 3382270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new OrMatcher(new FixedStringMatcher(ClassConstants.ATTR_SourceFile), 3392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new OrMatcher(new FixedStringMatcher(ClassConstants.ATTR_InnerClasses), 3402270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new FixedStringMatcher(ClassConstants.ATTR_EnclosingMethod))))), 341b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new AttributeAdder(targetClass, true))); 342b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 343b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Update the optimization information of the target class. 344b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassOptimizationInfo info = 345b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassOptimizationInfo.getClassOptimizationInfo(targetClass); 346b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (info != null) 347b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 348b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato info.merge(ClassOptimizationInfo.getClassOptimizationInfo(programClass)); 349b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 350b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 351b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Remember to replace the inlined class by the target class. 352b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato setTargetClass(programClass, targetClass); 353b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 354b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang //if (DEBUG) 355b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang //{ 356b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // System.out.println("=== After ===="); 357b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // targetClass.accept(new ClassPrinter()); 358b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang //} 359b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit the merged class, if required. 361b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (extraClassVisitor != null) 362b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 363b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato extraClassVisitor.visitProgramClass(programClass); 364b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 365b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 366b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 367b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 368b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 3692270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private boolean print(ProgramClass programClass, String message) 3702270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 3712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom System.out.println("Merge ["+targetClass.getName()+"] <- ["+programClass.getName()+"] "+message); 3722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 3732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom return true; 3742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 3752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 3762270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 377b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Small utility methods. 378b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 379b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 380b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether a given class is the only subclass of another given class. 381b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 382b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean isOnlySubClass(Clazz subClass, 383b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ProgramClass clazz) 384b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 385b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // TODO: The list of subclasses is not up to date. 386b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return clazz.subClasses != null && 387b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.subClasses.length == 1 && 388b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.subClasses[0].equals(subClass); 389b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 390b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 391b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 392b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 393b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns the set of indirectly implemented interfaces. 394b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 395b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private Set indirectlyImplementedInterfaces(Clazz clazz) 396b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 397b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Set set = new HashSet(); 398b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 399b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ReferencedClassVisitor referencedInterfaceCollector = 400b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ReferencedClassVisitor( 401b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ClassHierarchyTraveler(false, false, true, false, 402b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ClassCollector(set))); 403b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 404b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all superclasses and collect their interfaces. 405b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.superClassConstantAccept(referencedInterfaceCollector); 406b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 407b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all interfaces and collect their interfaces. 408b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.interfaceConstantsAccept(referencedInterfaceCollector); 409b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 410b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return set; 411b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 412b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 413b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 414b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 4152270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Returns the set of interface subclasses, not including the given class. 4162270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom */ 4172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private Set subInterfaces(Clazz clazz, Clazz exceptClass) 4182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 4192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom Set set = new HashSet(); 4202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 4212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Visit all subclasses, collecting the interface classes. 4222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom clazz.hierarchyAccept(false, false, false, true, 4232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new ClassAccessFilter(ClassConstants.ACC_INTERFACE, 0, 4242270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new ExceptClassesFilter(new Clazz[] { exceptClass }, 4252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new ClassCollector(set)))); 4262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 4272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom return set; 4282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 4292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 4302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 4312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom /** 432b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns the set of superclasses and interfaces that are initialized. 433b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 434b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private Set initializedSuperClasses(Clazz clazz) 435b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 436b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Set set = new HashSet(); 437b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 438b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all superclasses and interfaces, collecting the ones that have 439b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // static initializers. 440b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.hierarchyAccept(true, true, true, false, 441b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new StaticInitializerContainingClassFilter( 442b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new ClassCollector(set))); 443b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 444b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return set; 445b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 446b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 447b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 448b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 449b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns the set of superclasses and interfaces that are used in 450b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 'instanceof' tests. 451b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 452b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private Set instanceofedSuperClasses(Clazz clazz) 453b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 454b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Set set = new HashSet(); 455b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 456b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all superclasses and interfaces, collecting the ones that are 457b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // used in an 'instanceof' test. 458b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.hierarchyAccept(true, true, true, false, 459b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new InstanceofClassFilter( 460b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ClassCollector(set))); 461b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 462b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return set; 463b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 464b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 465b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 466b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 467b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns the set of superclasses that are caught as exceptions. 468b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 469b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private Set caughtSuperClasses(Clazz clazz) 470b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 471b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Don't bother if this isn't an exception at all. 4722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (!clazz.extends_(ClassConstants.NAME_JAVA_LANG_THROWABLE)) 473b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 474b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang return Collections.EMPTY_SET; 475b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 476b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 477b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Visit all superclasses, collecting the ones that are caught 478b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // (plus java.lang.Object, in the current implementation). 479b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Set set = new HashSet(); 480b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 481b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.hierarchyAccept(true, true, false, false, 482b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new CaughtClassFilter( 4839f606f95f03a75961498803e24bee6799a7c0885Ying Wang new ClassCollector(set))); 484b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 485b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return set; 486b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 487b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 488b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 489b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 4902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Returns whether the two given classes have fields with the same 4912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * names and descriptors. 492b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 493b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private boolean haveAnyIdenticalFields(Clazz clazz, Clazz targetClass) 494b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 495b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang MemberCounter counter = new MemberCounter(); 496b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 497b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Visit all fields, counting the with the same name and descriptor in 498b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // the target class. 499b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang clazz.fieldsAccept(new SimilarMemberVisitor(targetClass, true, false, false, false, 500b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang counter)); 501b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 502b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang return counter.getCount() > 0; 503b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 504b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 505b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 506b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 507b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether the given class would introduce any unwanted fields 508b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * in the target class. 509b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 510b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean introducesUnwantedFields(ProgramClass programClass, 511b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ProgramClass targetClass) 512b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 513b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // It's ok if the target class is never instantiated, without any other 514b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // subclasses except for maybe the source class. 515b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (!InstantiationClassMarker.isInstantiated(targetClass) && 516b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang (targetClass.subClasses == null || 517b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang isOnlySubClass(programClass, targetClass))) 518b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 519b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang return false; 520b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 521b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 522b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang MemberCounter counter = new MemberCounter(); 523b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 524b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Count all non-static fields in the the source class. 5252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom programClass.fieldsAccept(new MemberAccessFilter(0, ClassConstants.ACC_STATIC, 526b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang counter)); 527b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 528b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang return counter.getCount() > 0; 529b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 530b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 531b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 532b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 533b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Returns whether the given class or its subclasses shadow any fields in 534b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * the given target class. 535b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 536b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private boolean shadowsAnyFields(Clazz clazz, Clazz targetClass) 537b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 538b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang MemberCounter counter = new MemberCounter(); 539b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 540b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Visit all fields, counting the ones that are shadowing non-private 541b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // fields in the class hierarchy of the target class. 542b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang clazz.hierarchyAccept(true, false, false, true, 543b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new AllFieldVisitor( 544b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new SimilarMemberVisitor(targetClass, true, true, true, false, 5452270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, 546b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang counter)))); 547b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 548b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang return counter.getCount() > 0; 549b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 550b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 551b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 552b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 553b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * Returns whether the two given classes have class members with the same 554b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * name and descriptor. 555b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 556b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private boolean haveAnyIdenticalMethods(Clazz clazz, Clazz targetClass) 557b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 558b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato MemberCounter counter = new MemberCounter(); 559b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 560b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Visit all non-abstract methods, counting the ones that are also 561b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // present in the target class. 5622270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom clazz.methodsAccept(new MemberAccessFilter(0, ClassConstants.ACC_ABSTRACT, 563b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimilarMemberVisitor(targetClass, true, false, false, false, 5642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new MemberAccessFilter(0, ClassConstants.ACC_ABSTRACT, 565b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang counter)))); 566b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 567b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return counter.getCount() > 0; 568b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 569b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 570b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 571b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 572b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether the given class would introduce any abstract methods 573b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * in the target class. 574b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 575b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean introducesUnwantedAbstractMethods(Clazz clazz, 576b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ProgramClass targetClass) 577b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 578b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // It's ok if the target class is already abstract and it has at most 579b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // the class as a subclass. 580b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if ((targetClass.getAccessFlags() & 5812270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom (ClassConstants.ACC_ABSTRACT | 5822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ClassConstants.ACC_INTERFACE)) != 0 && 583b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (targetClass.subClasses == null || 584b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato isOnlySubClass(clazz, targetClass))) 585b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 586b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return false; 587b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 588b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 589b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato MemberCounter counter = new MemberCounter(); 590b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Set targetSet = new HashSet(); 591b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 592b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Collect all abstract methods, and similar abstract methods in the 593b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // class hierarchy of the target class. 5942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom clazz.methodsAccept(new MemberAccessFilter(ClassConstants.ACC_ABSTRACT, 0, 595b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MultiMemberVisitor(new MemberVisitor[] 596b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 597b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato counter, 598b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimilarMemberVisitor(targetClass, true, true, true, false, 5992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new MemberAccessFilter(ClassConstants.ACC_ABSTRACT, 0, 600b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberCollector(targetSet))) 601b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato }))); 602b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 603b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return targetSet.size() < counter.getCount(); 604b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 605b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 606b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 607b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 608b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether the given class overrides any methods in the given 609b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * target class. 610b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 611b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean overridesAnyMethods(Clazz clazz, Clazz targetClass) 612b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 613b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato MemberCounter counter = new MemberCounter(); 614b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 615b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all non-private non-static methods, counting the ones that are 616b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // being overridden in the class hierarchy of the target class. 6172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom clazz.methodsAccept(new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE | ClassConstants.ACC_STATIC | ClassConstants.ACC_ABSTRACT, 6182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.METHOD_NAME_CLINIT)), 6192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.METHOD_NAME_INIT)), 620b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimilarMemberVisitor(targetClass, true, true, false, false, 6212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE | ClassConstants.ACC_STATIC | ClassConstants.ACC_ABSTRACT, 622b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato counter)))))); 623b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 624b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return counter.getCount() > 0; 625b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 626b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 627b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 628b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 629b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether the given class or its subclasses shadow any methods in 630b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * the given target class. 631b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 632b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean shadowsAnyMethods(Clazz clazz, Clazz targetClass) 633b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 634b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato MemberCounter counter = new MemberCounter(); 635b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 636b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all private methods, counting the ones that are shadowing 637b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // non-private methods in the class hierarchy of the target class. 638b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.hierarchyAccept(true, false, false, true, 639b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new AllMethodVisitor( 6402270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new MemberAccessFilter(ClassConstants.ACC_PRIVATE, 0, 6412270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.METHOD_NAME_INIT)), 642b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimilarMemberVisitor(targetClass, true, true, true, false, 6432270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, 644b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato counter)))))); 645b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 646b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all static methods, counting the ones that are shadowing 647b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // non-private methods in the class hierarchy of the target class. 648b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.hierarchyAccept(true, false, false, true, 649b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new AllMethodVisitor( 6502270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new MemberAccessFilter(ClassConstants.ACC_STATIC, 0, 6512270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.METHOD_NAME_CLINIT)), 652b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimilarMemberVisitor(targetClass, true, true, true, false, 6532270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new MemberAccessFilter(0, ClassConstants.ACC_PRIVATE, 654b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato counter)))))); 655b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 656b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return counter.getCount() > 0; 657b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 658b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 659b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 660b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public static void setTargetClass(Clazz clazz, Clazz targetClass) 661b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 662b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz); 663b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (info != null) 664b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 665b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato info.setTargetClass(targetClass); 666b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 667b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 668b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 669b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 670b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public static Clazz getTargetClass(Clazz clazz) 671b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 672b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Clazz targetClass = null; 673b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 674b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Return the last target class, if any. 675b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato while (true) 676b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 677b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz); 678b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (info == null) 679b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 680b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return targetClass; 681b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 682b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 683b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz = info.getTargetClass(); 684b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (clazz == null) 685b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 686b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return targetClass; 687b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 688b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 689b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato targetClass = clazz; 690b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 691b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 692b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 693b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 694b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang /** 695b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang * This MemberVisitor copies field optimization info from copied fields. 696b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang */ 697b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private static class FieldOptimizationInfoCopier 698b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang extends SimplifiedVisitor 699b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang implements MemberVisitor 700b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 701b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public void visitProgramField(ProgramClass programClass, ProgramField programField) 702b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 703b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Copy the optimization info from the field that was just copied. 704b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang ProgramField copiedField = (ProgramField)programField.getVisitorInfo(); 705b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang Object info = copiedField.getVisitorInfo(); 706b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 707b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang programField.setVisitorInfo(info instanceof FieldOptimizationInfo ? 708b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new FieldOptimizationInfo((FieldOptimizationInfo)info) : 709b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang info); 710b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 711b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 712b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 713b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod) 714b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang { 715b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Linked methods share their optimization info. 716b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 717b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang } 7182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom} 719