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