1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/* 2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification 3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of Java bytecode. 4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59f606f95f03a75961498803e24bee6799a7c0885Ying Wang * Copyright (c) 2002-2009 Eric Lafortune (eric@graphics.cornell.edu) 6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it 8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free 9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option) 10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version. 11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT 13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details. 16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along 18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc., 19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard.optimize.peephole; 22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*; 24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.visitor.*; 25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.editor.*; 26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.*; 27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.visitor.*; 28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.optimize.KeepMarker; 29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.optimize.info.*; 30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.util.*; 31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport java.util.*; 33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/** 35b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This ClassVisitor inlines the classes that it visits in a given target class, 36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * whenever possible. 37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see RetargetedInnerClassAttributeRemover 39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see TargetClassChanger 40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see ClassReferenceFixer 41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see MemberReferenceFixer 42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @see AccessFixer 43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune 44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class ClassMerger 46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends SimplifiedVisitor 47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements ClassVisitor, 48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ConstantVisitor 49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{ 50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //* 51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private static final boolean DEBUG = false; 52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /*/ 53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private static boolean DEBUG = true; 54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //*/ 55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final ProgramClass targetClass; 58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final boolean allowAccessModification; 59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final boolean mergeInterfacesAggressively; 60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final ClassVisitor extraClassVisitor; 61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Creates a new ClassMerger that will merge classes into the given target 65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * class. 66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param targetClass the class into which all visited 67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * classes will be merged. 68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param allowAccessModification specifies whether the access modifiers 69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of classes can be changed in order to 70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * merge them. 71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param mergeInterfacesAggressively specifies whether interfaces may 72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * be merged aggressively. 73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public ClassMerger(ProgramClass targetClass, 75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato boolean allowAccessModification, 76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato boolean mergeInterfacesAggressively) 77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this(targetClass, allowAccessModification, mergeInterfacesAggressively, null); 79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Creates a new ClassMerger that will merge classes into the given target 84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * class. 85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param targetClass the class into which all visited 86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * classes will be merged. 87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param allowAccessModification specifies whether the access modifiers 88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of classes can be changed in order to 89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * merge them. 90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param mergeInterfacesAggressively specifies whether interfaces may 91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * be merged aggressively. 92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param extraClassVisitor an optional extra visitor for all 93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * merged classes. 94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public ClassMerger(ProgramClass targetClass, 96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato boolean allowAccessModification, 97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato boolean mergeInterfacesAggressively, 98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassVisitor extraClassVisitor) 99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.targetClass = targetClass; 101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.allowAccessModification = allowAccessModification; 102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.mergeInterfacesAggressively = mergeInterfacesAggressively; 103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.extraClassVisitor = extraClassVisitor; 104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for ClassVisitor. 108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitProgramClass(ProgramClass programClass) 110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //final String CLASS_NAME = "abc/Def"; 112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //DEBUG = programClass.getName().equals(CLASS_NAME) || 113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // targetClass.getName().equals(CLASS_NAME); 114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // TODO: Remove this when the class merger has stabilized. 116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Catch any unexpected exceptions from the actual visiting method. 117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato try 118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato visitProgramClass0(programClass); 120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato catch (RuntimeException ex) 122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println("Unexpected error while merging classes:"); 124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println(" Class = ["+programClass.getName()+"]"); 125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println(" Target class = ["+targetClass.getName()+"]"); 126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")"); 127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) 129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.accept(new ClassPrinter()); 131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato targetClass.accept(new ClassPrinter()); 132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw ex; 135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitProgramClass0(ProgramClass programClass) 139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (!programClass.equals(targetClass) && 141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Don't merge classes that must be preserved. 143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !KeepMarker.isKept(programClass) && 144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !KeepMarker.isKept(targetClass) && 145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Only merge classes that haven't been retargeted yet. 147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato getTargetClass(programClass) == null && 148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato getTargetClass(targetClass) == null && 149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Don't merge annotation classes, with all their introspection and 151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // infinite recursion. 152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (programClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_ANNOTATTION) == 0 && 153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1549f606f95f03a75961498803e24bee6799a7c0885Ying Wang // Only merge classes if we can change the access permissioms, or 155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // if they are in the same package, or 156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // if they are public and don't contain or invoke package visible 157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // class members. 158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (allowAccessModification || 159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ((programClass.getAccessFlags() & 160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato targetClass.getAccessFlags() & 161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassConstants.INTERNAL_ACC_PUBLIC) != 0 && 162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !PackageVisibleMemberContainingClassMarker.containsPackageVisibleMembers(programClass) && 163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !PackageVisibleMemberInvokingClassMarker.invokesPackageVisibleMembers(programClass)) || 164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassUtil.internalPackageName(programClass.getName()).equals( 165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassUtil.internalPackageName(targetClass.getName()))) && 166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Only merge two classes or two interfaces or two abstract classes, 168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // or a class into an interface with a single implementation. 169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ((programClass.getAccessFlags() & 170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (ClassConstants.INTERNAL_ACC_INTERFACE | 171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassConstants.INTERNAL_ACC_ABSTRACT)) == 172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (targetClass.getAccessFlags() & 173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (ClassConstants.INTERNAL_ACC_INTERFACE | 174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassConstants.INTERNAL_ACC_ABSTRACT)) || 175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (isOnlySubClass(programClass, targetClass) && 176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (programClass.getSuperClass().equals(targetClass) || 177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.getSuperClass().equals(targetClass.getSuperClass())))) && 178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // One class must not implement the other class indirectly. 180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !indirectlyImplementedInterfaces(programClass).contains(targetClass) && 181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !targetClass.extendsOrImplements(programClass) && 182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The two classes must have the same superclasses and interfaces 184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // with static initializers. 185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato initializedSuperClasses(programClass).equals(initializedSuperClasses(targetClass)) && 186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The two classes must have the same superclasses and interfaces 188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // that are tested with 'instanceof'. 189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instanceofedSuperClasses(programClass).equals(instanceofedSuperClasses(targetClass)) && 190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The two classes must have the same superclasses that are caught 192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // as exceptions. 193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato caughtSuperClasses(programClass).equals(caughtSuperClasses(targetClass)) && 194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The two classes must not both be part of a .class construct. 196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !(DotClassMarker.isDotClassed(programClass) && 197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato DotClassMarker.isDotClassed(targetClass)) && 198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The two classes must not introduce any unwanted fields. 200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !introducesUnwantedFields(programClass, targetClass) && 201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !introducesUnwantedFields(targetClass, programClass) && 202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The classes must not have clashing constructors. 204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !haveAnyIdenticalInitializers(programClass, targetClass) && 205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The classes must not introduce abstract methods, unless 207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // explicitly allowed. 208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (mergeInterfacesAggressively || 209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (!introducesUnwantedAbstractMethods(programClass, targetClass) && 210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !introducesUnwantedAbstractMethods(targetClass, programClass))) && 211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The classes must not override each others concrete methods. 213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !overridesAnyMethods(programClass, targetClass) && 214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !overridesAnyMethods(targetClass, programClass) && 215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The classes must not shadow each others non-private methods. 217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !shadowsAnyMethods(programClass, targetClass) && 218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !shadowsAnyMethods(targetClass, programClass)) 219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) 221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println("ClassMerger ["+programClass.getName()+"] -> ["+targetClass.getName()+"]"); 223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Source interface? ["+((programClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE)!=0)+"]"); 224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Target interface? ["+((targetClass.getAccessFlags() & ClassConstants.INTERNAL_ACC_INTERFACE)!=0)+"]"); 225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Source subclasses ["+programClass.subClasses+"]"); 226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Target subclasses ["+targetClass.subClasses+"]"); 227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Source superclass ["+programClass.getSuperClass().getName()+"]"); 228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(" Target superclass ["+targetClass.getSuperClass().getName()+"]"); 229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Combine the access flags. 232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int targetAccessFlags = targetClass.getAccessFlags(); 233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int sourceAccessFlags = programClass.getAccessFlags(); 234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato targetClass.u2accessFlags = 236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ((targetAccessFlags & 237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato sourceAccessFlags) & 2389f606f95f03a75961498803e24bee6799a7c0885Ying Wang (ClassConstants.INTERNAL_ACC_INTERFACE | 239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassConstants.INTERNAL_ACC_ABSTRACT)) | 240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ((targetAccessFlags | 241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato sourceAccessFlags) & 2429f606f95f03a75961498803e24bee6799a7c0885Ying Wang (ClassConstants.INTERNAL_ACC_PUBLIC | 243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassConstants.INTERNAL_ACC_ANNOTATTION | 244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassConstants.INTERNAL_ACC_ENUM)); 245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Copy over the superclass, unless it's the target class itself. 247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //if (!targetClass.getName().equals(programClass.getSuperName())) 248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //{ 249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // targetClass.u2superClass = 250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // new ConstantAdder(targetClass).addConstant(programClass, programClass.u2superClass); 251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //} 252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Copy over the interfaces that aren't present yet and that 254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // wouldn't cause loops in the class hierarchy. 255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.interfaceConstantsAccept( 256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ExceptClassConstantFilter(targetClass.getName(), 257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ImplementedClassConstantFilter(targetClass, 258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ImplementingClassConstantFilter(targetClass, 259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new InterfaceAdder(targetClass))))); 260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Copy over the class members. 262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato MemberAdder memberAdder = 2639f606f95f03a75961498803e24bee6799a7c0885Ying Wang new MemberAdder(targetClass); 264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.fieldsAccept(memberAdder); 266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.methodsAccept(memberAdder); 267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Copy over the other attributes. 269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.attributesAccept( 270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new AttributeAdder(targetClass, true)); 271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Update the optimization information of the target class. 273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassOptimizationInfo info = 274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassOptimizationInfo.getClassOptimizationInfo(targetClass); 275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (info != null) 276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato info.merge(ClassOptimizationInfo.getClassOptimizationInfo(programClass)); 278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Remember to replace the inlined class by the target class. 281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato setTargetClass(programClass, targetClass); 282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit the merged class, if required. 284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (extraClassVisitor != null) 285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato extraClassVisitor.visitProgramClass(programClass); 287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Small utility methods. 293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether a given class is the only subclass of another given class. 296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean isOnlySubClass(Clazz subClass, 298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ProgramClass clazz) 299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // TODO: The list of subclasses is not up to date. 301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return clazz.subClasses != null && 302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.subClasses.length == 1 && 303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.subClasses[0].equals(subClass); 304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns the set of indirectly implemented interfaces. 309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private Set indirectlyImplementedInterfaces(Clazz clazz) 311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Set set = new HashSet(); 313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ReferencedClassVisitor referencedInterfaceCollector = 315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ReferencedClassVisitor( 316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ClassHierarchyTraveler(false, false, true, false, 317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ClassCollector(set))); 318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all superclasses and collect their interfaces. 320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.superClassConstantAccept(referencedInterfaceCollector); 321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all interfaces and collect their interfaces. 323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.interfaceConstantsAccept(referencedInterfaceCollector); 324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 325b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return set; 326b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 327b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 328b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 329b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 330b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns the set of superclasses and interfaces that are initialized. 331b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 332b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private Set initializedSuperClasses(Clazz clazz) 333b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 334b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Set set = new HashSet(); 335b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 336b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all superclasses and interfaces, collecting the ones that have 337b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // static initializers. 338b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.hierarchyAccept(true, true, true, false, 3399f606f95f03a75961498803e24bee6799a7c0885Ying Wang new NamedMethodVisitor(ClassConstants.INTERNAL_METHOD_NAME_CLINIT, 3409f606f95f03a75961498803e24bee6799a7c0885Ying Wang ClassConstants.INTERNAL_METHOD_TYPE_INIT, 3419f606f95f03a75961498803e24bee6799a7c0885Ying Wang new MemberToClassVisitor( 3429f606f95f03a75961498803e24bee6799a7c0885Ying Wang new ClassCollector(set)))); 343b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 344b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return set; 345b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 346b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 347b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 348b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 349b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns the set of superclasses and interfaces that are used in 350b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 'instanceof' tests. 351b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 352b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private Set instanceofedSuperClasses(Clazz clazz) 353b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 354b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Set set = new HashSet(); 355b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 356b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all superclasses and interfaces, collecting the ones that are 357b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // used in an 'instanceof' test. 358b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.hierarchyAccept(true, true, true, false, 359b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new InstanceofClassFilter( 360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ClassCollector(set))); 361b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 362b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return set; 363b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 364b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 365b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 366b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 367b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns the set of superclasses that are caught as exceptions. 368b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 369b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private Set caughtSuperClasses(Clazz clazz) 370b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 371b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Set set = new HashSet(); 372b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 3739f606f95f03a75961498803e24bee6799a7c0885Ying Wang // Visit all superclasses, collecting the ones that are caught. 374b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.hierarchyAccept(true, true, false, false, 375b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new CaughtClassFilter( 3769f606f95f03a75961498803e24bee6799a7c0885Ying Wang new ClassCollector(set))); 377b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 378b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return set; 379b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 380b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 381b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 382b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 383b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether the given class would introduce any unwanted fields 384b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * in the target class. 385b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 386b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean introducesUnwantedFields(ProgramClass programClass, 387b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ProgramClass targetClass) 388b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 389b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // The class must not have any fields, or it must not be instantiated, 390b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // without any other subclasses. 391b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return 392b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato programClass.u2fieldsCount != 0 && 393b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (InstantiationClassMarker.isInstantiated(targetClass) || 394b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (targetClass.subClasses != null && 395b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !isOnlySubClass(programClass, targetClass))); 396b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 397b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 398b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 399b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 400b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether the two given classes have initializers with the same 401b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * descriptors. 402b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 403b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean haveAnyIdenticalInitializers(Clazz clazz, Clazz targetClass) 404b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 405b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato MemberCounter counter = new MemberCounter(); 406b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 407b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // TODO: Currently checking shared methods, not just initializers. 408b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // TODO: Allow identical methods. 409b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all methods, counting the ones that are also present in the 410b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // target class. 411b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.methodsAccept(//new MemberNameFilter(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_INIT), 412b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimilarMemberVisitor(targetClass, true, false, false, false, 413b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_ABSTRACT, 414b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato counter))); 415b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 416b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return counter.getCount() > 0; 417b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 418b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 419b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 420b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 421b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether the given class would introduce any abstract methods 422b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * in the target class. 423b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 424b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean introducesUnwantedAbstractMethods(Clazz clazz, 425b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ProgramClass targetClass) 426b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 427b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // It's ok if the target class is already abstract and it has at most 428b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // the class as a subclass. 429b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if ((targetClass.getAccessFlags() & 430b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (ClassConstants.INTERNAL_ACC_ABSTRACT | 431b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassConstants.INTERNAL_ACC_INTERFACE)) != 0 && 432b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (targetClass.subClasses == null || 433b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato isOnlySubClass(clazz, targetClass))) 434b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 435b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return false; 436b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 437b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 438b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato MemberCounter counter = new MemberCounter(); 439b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Set targetSet = new HashSet(); 440b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 441b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Collect all abstract methods, and similar abstract methods in the 442b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // class hierarchy of the target class. 443b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.methodsAccept(new MemberAccessFilter(ClassConstants.INTERNAL_ACC_ABSTRACT, 0, 444b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MultiMemberVisitor(new MemberVisitor[] 445b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 446b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato counter, 447b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimilarMemberVisitor(targetClass, true, true, true, false, 448b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberAccessFilter(ClassConstants.INTERNAL_ACC_ABSTRACT, 0, 449b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberCollector(targetSet))) 450b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato }))); 451b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 452b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return targetSet.size() < counter.getCount(); 453b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 454b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 455b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 456b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 457b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether the given class overrides any methods in the given 458b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * target class. 459b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 460b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean overridesAnyMethods(Clazz clazz, Clazz targetClass) 461b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 462b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato MemberCounter counter = new MemberCounter(); 463b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 464b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all non-private non-static methods, counting the ones that are 465b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // being overridden in the class hierarchy of the target class. 466b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.methodsAccept(new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC | ClassConstants.INTERNAL_ACC_ABSTRACT, 467b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_CLINIT)), 468b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_INIT)), 469b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimilarMemberVisitor(targetClass, true, true, false, false, 470b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE | ClassConstants.INTERNAL_ACC_STATIC | ClassConstants.INTERNAL_ACC_ABSTRACT, 471b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato counter)))))); 472b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 473b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return counter.getCount() > 0; 474b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 475b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 476b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 477b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 478b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Returns whether the given class or its subclasses shadow any methods in 479b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * the given target class. 480b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 481b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private boolean shadowsAnyMethods(Clazz clazz, Clazz targetClass) 482b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 483b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato MemberCounter counter = new MemberCounter(); 484b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 485b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all private methods, counting the ones that are shadowing 486b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // non-private methods in the class hierarchy of the target class. 487b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.hierarchyAccept(true, false, false, true, 488b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new AllMethodVisitor( 489b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberAccessFilter(ClassConstants.INTERNAL_ACC_PRIVATE, 0, 490b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_INIT)), 491b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimilarMemberVisitor(targetClass, true, true, true, false, 492b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, 493b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato counter)))))); 494b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 495b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit all static methods, counting the ones that are shadowing 496b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // non-private methods in the class hierarchy of the target class. 497b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz.hierarchyAccept(true, false, false, true, 498b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new AllMethodVisitor( 499b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberAccessFilter(ClassConstants.INTERNAL_ACC_STATIC, 0, 500b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberNameFilter(new NotMatcher(new FixedStringMatcher(ClassConstants.INTERNAL_METHOD_NAME_CLINIT)), 501b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimilarMemberVisitor(targetClass, true, true, true, false, 502b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new MemberAccessFilter(0, ClassConstants.INTERNAL_ACC_PRIVATE, 503b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato counter)))))); 504b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 505b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return counter.getCount() > 0; 506b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 507b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 508b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 509b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public static void setTargetClass(Clazz clazz, Clazz targetClass) 510b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 511b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz); 512b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (info != null) 513b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 514b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato info.setTargetClass(targetClass); 515b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 516b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 517b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 518b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 519b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public static Clazz getTargetClass(Clazz clazz) 520b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 521b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Clazz targetClass = null; 522b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 523b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Return the last target class, if any. 524b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato while (true) 525b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 526b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ClassOptimizationInfo info = ClassOptimizationInfo.getClassOptimizationInfo(clazz); 527b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (info == null) 528b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 529b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return targetClass; 530b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 531b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 532b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato clazz = info.getTargetClass(); 533b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (clazz == null) 534b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 535b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato return targetClass; 536b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 537b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 538b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato targetClass = clazz; 539b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 540b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 541b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}