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.attribute.*;
25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.visitor.*;
26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.*;
27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.constant.visitor.ConstantVisitor;
28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.editor.*;
29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.*;
30b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.visitor.InstructionVisitor;
31b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.*;
329f606f95f03a75961498803e24bee6799a7c0885Ying Wangimport proguard.classfile.visitor.MemberVisitor;
33b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.optimize.info.*;
34b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
359f606f95f03a75961498803e24bee6799a7c0885Ying Wangimport java.util.Stack;
36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/**
38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This AttributeVisitor inlines short methods or methods that are only invoked
39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * once, in the code attributes that it visits.
40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato *
41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune
42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */
43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class MethodInliner
44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends      SimplifiedVisitor
45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements   AttributeVisitor,
46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             InstructionVisitor,
47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             ConstantVisitor,
48b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             MemberVisitor
49b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{
50b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final int MAXIMUM_INLINED_CODE_LENGTH       = Integer.parseInt(System.getProperty("maximum.inlined.code.length",      "8"));
519f606f95f03a75961498803e24bee6799a7c0885Ying Wang    private static final int MAXIMUM_RESULTING_CODE_LENGTH_JSE = Integer.parseInt(System.getProperty("maximum.resulting.code.length", "8000"));
52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final int MAXIMUM_RESULTING_CODE_LENGTH_JME = Integer.parseInt(System.getProperty("maximum.resulting.code.length", "2000"));
53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final int MAXIMUM_CODE_EXPANSION            = 2;
54b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final int MAXIMUM_EXTRA_CODE_LENGTH         = 128;
55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    //*
57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static final boolean DEBUG = false;
58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /*/
59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private static       boolean DEBUG = true;
60b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    //*/
61b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final boolean            microEdition;
64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final boolean            allowAccessModification;
65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final boolean            inlineSingleInvocations;
66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final InstructionVisitor extraInlinedInvocationVisitor;
67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final CodeAttributeComposer codeAttributeComposer = new CodeAttributeComposer();
69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final AccessMethodMarker    accessMethodMarker    = new AccessMethodMarker();
70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final CatchExceptionMarker  catchExceptionMarker  = new CatchExceptionMarker();
71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private final StackSizeComputer     stackSizeComputer     = new StackSizeComputer();
72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private ProgramClass       targetClass;
74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private ProgramMethod      targetMethod;
75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private ConstantAdder      constantAdder;
76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private ExceptionInfoAdder exceptionInfoAdder;
77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int                estimatedResultingCodeLength;
78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean            inlining;
79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private Stack              inliningMethods              = new Stack();
80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean            emptyInvokingStack;
81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int                uninitializedObjectCount;
82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private int                variableOffset;
83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean            inlined;
84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private boolean            inlinedAny;
85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new MethodInliner.
89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param microEdition            indicates whether the resulting code is
90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                targeted at Java Micro Edition.
91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param allowAccessModification indicates whether the access modifiers of
92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                classes and class members can be changed
93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                in order to inline methods.
94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param inlineSingleInvocations indicates whether the single invocations
95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                should be inlined, or, alternatively,
96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                short methods.
97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public MethodInliner(boolean microEdition,
99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                         boolean allowAccessModification,
100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                         boolean inlineSingleInvocations)
101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this(microEdition,
103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             allowAccessModification,
104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             inlineSingleInvocations,
105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             null);
106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Creates a new MethodInliner.
111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param microEdition            indicates whether the resulting code is
112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                targeted at Java Micro Edition.
113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param allowAccessModification indicates whether the access modifiers of
114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                classes and class members can be changed
115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                in order to inline methods.
116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param inlineSingleInvocations indicates whether the single invocations
117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                should be inlined, or, alternatively,
118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                short methods.
119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * @param extraInlinedInvocationVisitor an optional extra visitor for all
120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     *                                      inlined invocation instructions.
121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public MethodInliner(boolean            microEdition,
123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                         boolean            allowAccessModification,
124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                         boolean            inlineSingleInvocations,
125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                         InstructionVisitor extraInlinedInvocationVisitor)
126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.microEdition                  = microEdition;
128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.allowAccessModification       = allowAccessModification;
129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.inlineSingleInvocations       = inlineSingleInvocations;
130b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        this.extraInlinedInvocationVisitor = extraInlinedInvocationVisitor;
131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for AttributeVisitor.
135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnyAttribute(Clazz clazz, Attribute attribute) {}
137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute)
140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (!inlining)
142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//            codeAttributeComposer.DEBUG = DEBUG =
144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//                clazz.getName().equals("abc/Def") &&
145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//                method.getName(clazz).equals("abc");
146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            targetClass                  = (ProgramClass)clazz;
148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            targetMethod                 = (ProgramMethod)method;
149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            constantAdder                = new ConstantAdder(targetClass);
150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            exceptionInfoAdder           = new ExceptionInfoAdder(targetClass, codeAttributeComposer);
151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            estimatedResultingCodeLength = codeAttribute.u4codeLength;
152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            inliningMethods.clear();
153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            uninitializedObjectCount     = method.getName(clazz).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ? 1 : 0;
154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            inlinedAny                   = false;
155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            codeAttributeComposer.reset();
156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            stackSizeComputer.visitCodeAttribute(clazz, method, codeAttribute);
157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Append the body of the code.
159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            copyCode(clazz, method, codeAttribute);
160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            targetClass   = null;
162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            targetMethod  = null;
163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            constantAdder = null;
164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Update the code attribute if any code has been inlined.
166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (inlinedAny)
167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                codeAttributeComposer.visitCodeAttribute(clazz, method, codeAttribute);
169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Update the accessing flags.
171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                codeAttribute.instructionsAccept(clazz, method, accessMethodMarker);
172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Update the exception catching flags.
174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                catchExceptionMarker.visitCodeAttribute(clazz, method, codeAttribute);
175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Only inline the method if it is invoked once or if it is short.
179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else if ((inlineSingleInvocations ?
180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                      MethodInvocationMarker.getInvocationCount(method) == 1 :
181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                      codeAttribute.u4codeLength <= MAXIMUM_INLINED_CODE_LENGTH) &&
182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                 estimatedResultingCodeLength + codeAttribute.u4codeLength <
183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                 (microEdition ?
184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                     MAXIMUM_RESULTING_CODE_LENGTH_JME :
185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                     MAXIMUM_RESULTING_CODE_LENGTH_JSE))
186b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (DEBUG)
188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                System.out.println("MethodInliner: inlining ["+
190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"] in ["+
191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                   targetClass.getName()+"."+targetMethod.getName(targetClass)+targetMethod.getDescriptor(targetClass)+"]");
192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Ignore the removal of the original method invocation,
195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // the addition of the parameter setup, and
196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // the modification of a few inlined instructions.
197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            estimatedResultingCodeLength += codeAttribute.u4codeLength;
198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Append instructions to store the parameters.
200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            storeParameters(clazz, method);
201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Inline the body of the code.
203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            copyCode(clazz, method, codeAttribute);
204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            inlined    = true;
206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            inlinedAny = true;
207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Appends instructions to pop the parameters for the given method, storing
213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * them in new local variables.
214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void storeParameters(Clazz clazz, Method method)
216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String descriptor = method.getDescriptor(clazz);
218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        boolean isStatic =
220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (method.getAccessFlags() & ClassConstants.INTERNAL_ACC_STATIC) != 0;
221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Count the number of parameters, taking into account their categories.
223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int parameterCount  = ClassUtil.internalMethodParameterCount(descriptor);
224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int parameterSize   = ClassUtil.internalMethodParameterSize(descriptor);
225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int parameterOffset = isStatic ? 0 : 1;
226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Store the parameter types.
228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        String[] parameterTypes = new String[parameterSize];
229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        InternalTypeEnumeration internalTypeEnumeration =
231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            new InternalTypeEnumeration(descriptor);
232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        for (int parameterIndex = 0; parameterIndex < parameterSize; parameterIndex++)
234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String parameterType = internalTypeEnumeration.nextType();
236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            parameterTypes[parameterIndex] = parameterType;
237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (ClassUtil.internalTypeSize(parameterType) == 2)
238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                parameterIndex++;
240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeComposer.beginCodeFragment(parameterSize+1);
244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Go over the parameter types backward, storing the stack entries
246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // in their corresponding variables.
247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        for (int parameterIndex = parameterSize-1; parameterIndex >= 0; parameterIndex--)
248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            String parameterType = parameterTypes[parameterIndex];
250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (parameterType != null)
251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                byte opcode;
253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                switch (parameterType.charAt(0))
254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    case ClassConstants.INTERNAL_TYPE_BOOLEAN:
256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    case ClassConstants.INTERNAL_TYPE_BYTE:
257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    case ClassConstants.INTERNAL_TYPE_CHAR:
258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    case ClassConstants.INTERNAL_TYPE_SHORT:
259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    case ClassConstants.INTERNAL_TYPE_INT:
260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        opcode = InstructionConstants.OP_ISTORE;
261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        break;
262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    case ClassConstants.INTERNAL_TYPE_LONG:
264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        opcode = InstructionConstants.OP_LSTORE;
265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        break;
266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    case ClassConstants.INTERNAL_TYPE_FLOAT:
268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        opcode = InstructionConstants.OP_FSTORE;
269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        break;
270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    case ClassConstants.INTERNAL_TYPE_DOUBLE:
272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        opcode = InstructionConstants.OP_DSTORE;
273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        break;
274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    default:
276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        opcode = InstructionConstants.OP_ASTORE;
277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        break;
278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                codeAttributeComposer.appendInstruction(parameterSize-parameterIndex-1,
281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                        new VariableInstruction(opcode, variableOffset + parameterOffset + parameterIndex).shrink());
282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Put the 'this' reference in variable 0 (plus offset).
286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (!isStatic)
287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            codeAttributeComposer.appendInstruction(parameterSize,
289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                    new VariableInstruction(InstructionConstants.OP_ASTORE, variableOffset).shrink());
290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeComposer.endCodeFragment();
293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    /**
297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     * Appends the code of the given code attribute.
298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato     */
299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    private void copyCode(Clazz clazz, Method method, CodeAttribute codeAttribute)
300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // The code may expand, due to expanding constant and variable
302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // instructions.
303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeComposer.beginCodeFragment(codeAttribute.u4codeLength);
304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Copy the instructions.
306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttribute.instructionsAccept(clazz, method, this);
307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
308cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang        // Copy the exceptions.
309cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang        codeAttribute.exceptionsAccept(clazz, method, exceptionInfoAdder);
310cfead78069f3dc32998dc118ee08cab3867acea2Ying Wang
3119f606f95f03a75961498803e24bee6799a7c0885Ying Wang        // Append a label just after the code.
3129f606f95f03a75961498803e24bee6799a7c0885Ying Wang        codeAttributeComposer.appendLabel(codeAttribute.u4codeLength);
3139f606f95f03a75961498803e24bee6799a7c0885Ying Wang
314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeComposer.endCodeFragment();
315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for InstructionVisitor.
319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnyInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, Instruction instruction)
321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeComposer.appendInstruction(offset, instruction.shrink());
323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
325b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
326b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction)
327b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
328b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Are we inlining this instruction?
329b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (inlining)
330b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
331b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Replace any return instructions by branches to the end of the code.
332b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            switch (simpleInstruction.opcode)
333b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
334b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_IRETURN:
335b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_LRETURN:
336b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_FRETURN:
337b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_DRETURN:
338b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_ARETURN:
339b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                case InstructionConstants.OP_RETURN:
340b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // Are we not at the last instruction?
341b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    if (offset < codeAttribute.u4codeLength-1)
342b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    {
343b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        // Replace the return instruction by a branch instruction.
344b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        Instruction branchInstruction =
345b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            new BranchInstruction(InstructionConstants.OP_GOTO_W,
346b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                  codeAttribute.u4codeLength - offset);
347b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
348b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        codeAttributeComposer.appendInstruction(offset,
349b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                                                                branchInstruction.shrink());
350b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    }
351b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    else
352b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    {
353b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        // Just leave out the instruction, but put in a label,
354b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        // for the sake of any other branch instructions.
355b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        codeAttributeComposer.appendLabel(offset);
356b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    }
357b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
358b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    return;
359b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
361b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
362b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeComposer.appendInstruction(offset, simpleInstruction.shrink());
363b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
364b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
365b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
366b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction)
367b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
368b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Are we inlining this instruction?
369b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (inlining)
370b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
371b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Update the variable index.
372b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            variableInstruction.variableIndex += variableOffset;
373b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
374b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
375b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeComposer.appendInstruction(offset, variableInstruction.shrink());
376b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
377b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
378b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
379b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction)
380b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
381b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Is it a method invocation?
382b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        switch (constantInstruction.opcode)
383b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
384b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_NEW:
385b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                uninitializedObjectCount++;
386b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
387b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
388b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_INVOKEVIRTUAL:
389b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_INVOKESPECIAL:
390b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_INVOKESTATIC:
391b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            case InstructionConstants.OP_INVOKEINTERFACE:
392b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // See if we can inline it.
393b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                inlined = false;
394b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
395b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Append a label, in case the invocation will be inlined.
396b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                codeAttributeComposer.appendLabel(offset);
397b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
398b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                emptyInvokingStack =
399b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    !inlining &&
400b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    stackSizeComputer.isReachable(offset) &&
401b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    stackSizeComputer.getStackSize(offset) == 0;
402b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
403b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                variableOffset += codeAttribute.u2maxLocals;
404b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
405b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                clazz.constantPoolEntryAccept(constantInstruction.constantIndex, this);
406b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
407b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                variableOffset -= codeAttribute.u2maxLocals;
408b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
409b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                // Was the method inlined?
410b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                if (inlined)
411b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                {
412b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    if (extraInlinedInvocationVisitor != null)
413b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    {
414b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                        extraInlinedInvocationVisitor.visitConstantInstruction(clazz, method, codeAttribute, offset, constantInstruction);
415b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    }
416b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
417b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    // The invocation itself is no longer necessary.
418b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                    return;
419b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                }
420b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
421b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                break;
422b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
423b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
424b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        // Are we inlining this instruction?
425b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (inlining)
426b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
427b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Make sure the constant is present in the constant pool of the
428b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // target class.
429b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            constantInstruction.constantIndex =
430b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                constantAdder.addConstant(clazz, constantInstruction.constantIndex);
431b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
432b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
433b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        codeAttributeComposer.appendInstruction(offset, constantInstruction.shrink());
434b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
435b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
436b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
437b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for ConstantVisitor.
438b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
439b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitInterfaceMethodrefConstant(Clazz clazz, InterfaceMethodrefConstant interfaceMethodrefConstant) {}
440b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
441b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
442b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitMethodrefConstant(Clazz clazz, MethodrefConstant methodrefConstant)
443b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
444b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        methodrefConstant.referencedMemberAccept(this);
445b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
446b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
447b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
448b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    // Implementations for MemberVisitor.
449b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
450b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitAnyMember(Clazz Clazz, Member member) {}
451b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
452b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
453b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    public void visitProgramMethod(ProgramClass programClass, ProgramMethod programMethod)
454b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    {
455b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        int accessFlags = programMethod.getAccessFlags();
456b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
457b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        if (// Only inline the method if it is private, static, or final.
458b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (accessFlags & (ClassConstants.INTERNAL_ACC_PRIVATE |
459b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            ClassConstants.INTERNAL_ACC_STATIC  |
4609f606f95f03a75961498803e24bee6799a7c0885Ying Wang                            ClassConstants.INTERNAL_ACC_FINAL)) != 0                               &&
461b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
462b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Only inline the method if it is not synchronized, etc.
463b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (accessFlags & (ClassConstants.INTERNAL_ACC_SYNCHRONIZED |
464b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            ClassConstants.INTERNAL_ACC_NATIVE       |
465b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                            ClassConstants.INTERNAL_ACC_INTERFACE    |
4669f606f95f03a75961498803e24bee6799a7c0885Ying Wang                            ClassConstants.INTERNAL_ACC_ABSTRACT)) == 0                            &&
467b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
468b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Don't inline an <init> method, except in an <init> method in the
469b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // same class.
470b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//            (!programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT) ||
471b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//             (programClass.equals(targetClass) &&
472b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//              targetMethod.getName(targetClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))) &&
4739f606f95f03a75961498803e24bee6799a7c0885Ying Wang            !programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT)  &&
474b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
475b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Don't inline a method into itself.
476b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (!programMethod.equals(targetMethod) ||
4779f606f95f03a75961498803e24bee6799a7c0885Ying Wang             !programClass.equals(targetClass))                                                    &&
478b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
479b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Only inline the method if it isn't recursing.
4809f606f95f03a75961498803e24bee6799a7c0885Ying Wang            !inliningMethods.contains(programMethod)                                               &&
481b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
482b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Only inline the method if its target class has at least the
483b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // same version number as the source class, in order to avoid
484b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // introducing incompatible constructs.
4859f606f95f03a75961498803e24bee6799a7c0885Ying Wang            targetClass.u4version >= programClass.u4version                                        &&
486b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
487b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Only inline the method if it doesn't invoke a super method, or if
488b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // it is in the same class.
489b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (!SuperInvocationMarker.invokesSuperMethods(programMethod) ||
4909f606f95f03a75961498803e24bee6799a7c0885Ying Wang             programClass.equals(targetClass))                                                     &&
491b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
492b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Only inline the method if it doesn't branch backward while there
493b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // are uninitialized objects.
494b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (!BackwardBranchMarker.branchesBackward(programMethod) ||
4959f606f95f03a75961498803e24bee6799a7c0885Ying Wang             uninitializedObjectCount == 0)                                                        &&
496b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
497b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Only inline if the code access of the inlined method allows it.
498b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (allowAccessModification ||
499b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato             ((!AccessMethodMarker.accessesPrivateCode(programMethod) ||
500b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               programClass.equals(targetClass)) &&
501b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
502b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato              (!AccessMethodMarker.accessesPackageCode(programMethod) ||
503b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato               ClassUtil.internalPackageName(programClass.getName()).equals(
5049f606f95f03a75961498803e24bee6799a7c0885Ying Wang               ClassUtil.internalPackageName(targetClass.getName())))))                            &&
505b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
506b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//               (!AccessMethodMarker.accessesProtectedCode(programMethod) ||
507b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//                targetClass.extends_(programClass) ||
508b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato//                targetClass.implements_(programClass)) ||
509b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (!AccessMethodMarker.accessesProtectedCode(programMethod) ||
5109f606f95f03a75961498803e24bee6799a7c0885Ying Wang             programClass.equals(targetClass))                                                     &&
511b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
512b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Only inline the method if it doesn't catch exceptions, or if it
513b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // is invoked with an empty stack.
514b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (!CatchExceptionMarker.catchesExceptions(programMethod) ||
5159f606f95f03a75961498803e24bee6799a7c0885Ying Wang             emptyInvokingStack)                                                                   &&
516b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
5179f606f95f03a75961498803e24bee6799a7c0885Ying Wang            // Only inline the method if it comes from the same class or from
5189f606f95f03a75961498803e24bee6799a7c0885Ying Wang            // a class with a static initializer.
519b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            (programClass.equals(targetClass) ||
5209f606f95f03a75961498803e24bee6799a7c0885Ying Wang             programClass.findMethod(ClassConstants.INTERNAL_METHOD_NAME_CLINIT,
5219f606f95f03a75961498803e24bee6799a7c0885Ying Wang                                     ClassConstants.INTERNAL_METHOD_TYPE_CLINIT) == null))
5229f606f95f03a75961498803e24bee6799a7c0885Ying Wang        {
5239f606f95f03a75961498803e24bee6799a7c0885Ying Wang//            System.out.print("MethodInliner: inlining ");
5249f606f95f03a75961498803e24bee6799a7c0885Ying Wang//            programMethod.accept(programClass, new SimpleClassPrinter(true));
5259f606f95f03a75961498803e24bee6799a7c0885Ying Wang//            System.out.print("               in       ");
5269f606f95f03a75961498803e24bee6799a7c0885Ying Wang//            targetMethod.accept(targetClass, new SimpleClassPrinter(true));
5279f606f95f03a75961498803e24bee6799a7c0885Ying Wang//
5289f606f95f03a75961498803e24bee6799a7c0885Ying Wang//            System.out.println("  Private:   "+
5299f606f95f03a75961498803e24bee6799a7c0885Ying Wang//                               (!AccessMethodMarker.accessesPrivateCode(programMethod) ||
5309f606f95f03a75961498803e24bee6799a7c0885Ying Wang//                                programClass.equals(targetClass)));
5319f606f95f03a75961498803e24bee6799a7c0885Ying Wang//
5329f606f95f03a75961498803e24bee6799a7c0885Ying Wang//            System.out.println("  Package:   "+
5339f606f95f03a75961498803e24bee6799a7c0885Ying Wang//                               (!AccessMethodMarker.accessesPackageCode(programMethod) ||
5349f606f95f03a75961498803e24bee6799a7c0885Ying Wang//                                ClassUtil.internalPackageName(programClass.getName()).equals(
5359f606f95f03a75961498803e24bee6799a7c0885Ying Wang//                                ClassUtil.internalPackageName(targetClass.getName()))));
5369f606f95f03a75961498803e24bee6799a7c0885Ying Wang//
5379f606f95f03a75961498803e24bee6799a7c0885Ying Wang//            System.out.println("  Protected: "+
5389f606f95f03a75961498803e24bee6799a7c0885Ying Wang//                               ((!AccessMethodMarker.accessesProtectedCode(programMethod) ||
5399f606f95f03a75961498803e24bee6799a7c0885Ying Wang//                                 targetClass.extends_(programClass) ||
5409f606f95f03a75961498803e24bee6799a7c0885Ying Wang//                                 targetClass.implements_(programClass)) ||
5419f606f95f03a75961498803e24bee6799a7c0885Ying Wang//                                ClassUtil.internalPackageName(programClass.getName()).equals(
5429f606f95f03a75961498803e24bee6799a7c0885Ying Wang//                                ClassUtil.internalPackageName(targetClass.getName()))));
5439f606f95f03a75961498803e24bee6799a7c0885Ying Wang
5449f606f95f03a75961498803e24bee6799a7c0885Ying Wang            boolean oldInlining = inlining;
545b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            inlining = true;
546b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            inliningMethods.push(programMethod);
547b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
548b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Inline the method body.
549b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            programMethod.attributesAccept(programClass, this);
550b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
551b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            // Update the optimization information of the target method.
552b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            MethodOptimizationInfo info =
553b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                MethodOptimizationInfo.getMethodOptimizationInfo(targetMethod);
554b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            if (info != null)
555b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            {
556b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato                info.merge(MethodOptimizationInfo.getMethodOptimizationInfo(programMethod));
557b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            }
558b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato
559b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            inlining = oldInlining;
560b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            inliningMethods.pop();
561b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
562b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        else if (programMethod.getName(programClass).equals(ClassConstants.INTERNAL_METHOD_NAME_INIT))
563b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        {
564b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato            uninitializedObjectCount--;
565b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato        }
566b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato    }
567b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato}
568