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