1b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/* 2b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ProGuard -- shrinking, optimization, obfuscation, and preverification 3b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of Java bytecode. 4b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 52270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Copyright (c) 2002-2014 Eric Lafortune (eric@graphics.cornell.edu) 6b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 7b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is free software; you can redistribute it and/or modify it 8b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * under the terms of the GNU General Public License as published by the Free 9b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Software Foundation; either version 2 of the License, or (at your option) 10b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * any later version. 11b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 12b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This program is distributed in the hope that it will be useful, but WITHOUT 13b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 14b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 15b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * more details. 16b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 17b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * You should have received a copy of the GNU General Public License along 18b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * with this program; if not, write to the Free Software Foundation, Inc., 19b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 21b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopackage proguard.optimize.evaluation; 22b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 23b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.*; 24b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.*; 25b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.attribute.visitor.AttributeVisitor; 26b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.editor.*; 27b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.*; 28b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.instruction.visitor.InstructionVisitor; 29b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.classfile.util.*; 302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.classfile.visitor.ClassPrinter; 312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.evaluation.TracedVariables; 32b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimport proguard.evaluation.value.*; 332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport proguard.optimize.info.SideEffectInstructionChecker; 342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstromimport java.util.Arrays; 36b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 37b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato/** 38b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * This AttributeVisitor simplifies the code attributes that it visits, based 39b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * on partial evaluation. 40b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * 41b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @author Eric Lafortune 42b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 43b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratopublic class EvaluationSimplifier 44b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoextends SimplifiedVisitor 45b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onoratoimplements AttributeVisitor, 46b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionVisitor 47b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato{ 48b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private static final int POS_ZERO_FLOAT_BITS = Float.floatToIntBits(0.0f); 49b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private static final long POS_ZERO_DOUBLE_BITS = Double.doubleToLongBits(0.0); 50b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang 51b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //* 52b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private static final boolean DEBUG = false; 53b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /*/ 542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private static boolean DEBUG = System.getProperty("es") != null; 55b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato //*/ 56b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 57b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final InstructionVisitor extraInstructionVisitor; 58b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 59b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private final PartialEvaluator partialEvaluator; 60b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private final SideEffectInstructionChecker sideEffectInstructionChecker = new SideEffectInstructionChecker(true, true); 61b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang private final CodeAttributeEditor codeAttributeEditor = new CodeAttributeEditor(false, true); 62b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 63b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 64b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 65b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Creates a new EvaluationSimplifier. 66b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 67b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public EvaluationSimplifier() 68b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 69b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this(new PartialEvaluator(), null); 70b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 71b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 72b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 73b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 74b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Creates a new EvaluationSimplifier. 75b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param partialEvaluator the partial evaluator that will 76b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * execute the code and provide 77b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * information about the results. 78b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * @param extraInstructionVisitor an optional extra visitor for all 79b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * simplified instructions. 80b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 81b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public EvaluationSimplifier(PartialEvaluator partialEvaluator, 82b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionVisitor extraInstructionVisitor) 83b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 84b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.partialEvaluator = partialEvaluator; 85b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato this.extraInstructionVisitor = extraInstructionVisitor; 86b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 87b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 88b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 89b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for AttributeVisitor. 90b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 91b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitAnyAttribute(Clazz clazz, Attribute attribute) {} 92b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 93b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 94b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitCodeAttribute(Clazz clazz, Method method, CodeAttribute codeAttribute) 95b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 96b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// DEBUG = 97b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// clazz.getName().equals("abc/Def") && 98b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato// method.getName(clazz).equals("abc"); 99b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 100b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // TODO: Remove this when the evaluation simplifier has stabilized. 101b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Catch any unexpected exceptions from the actual visiting method. 102b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato try 103b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 104b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Process the code. 105b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato visitCodeAttribute0(clazz, method, codeAttribute); 106b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 107b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato catch (RuntimeException ex) 108b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 109b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println("Unexpected error while simplifying instructions after partial evaluation:"); 110b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println(" Class = ["+clazz.getName()+"]"); 111b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println(" Method = ["+method.getName(clazz)+method.getDescriptor(clazz)+"]"); 112b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println(" Exception = ["+ex.getClass().getName()+"] ("+ex.getMessage()+")"); 113b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.err.println("Not optimizing this method"); 114b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 115b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) 116b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 117b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato method.accept(clazz, new ClassPrinter()); 118b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 119b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato throw ex; 120b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 121b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 122b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 123b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 124b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 125b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitCodeAttribute0(Clazz clazz, Method method, CodeAttribute codeAttribute) 126b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 127b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) 128b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 129b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato System.out.println(); 1302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom System.out.println("EvaluationSimplifier ["+clazz.getName()+"."+method.getName(clazz)+method.getDescriptor(clazz)+"]"); 131b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 132b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 133b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Evaluate the method. 134b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato partialEvaluator.visitCodeAttribute(clazz, method, codeAttribute); 135b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 136b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int codeLength = codeAttribute.u4codeLength; 137b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 138b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Reset the code changes. 139b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.reset(codeLength); 140b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 141b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Replace any instructions that can be simplified. 142b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int offset = 0; offset < codeLength; offset++) 143b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 144b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (partialEvaluator.isTraced(offset)) 145b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 146b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction = InstructionFactory.create(codeAttribute.code, 147b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset); 148b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 149b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction.accept(clazz, method, codeAttribute, offset, this); 150b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 151b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 152b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 153b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Apply all accumulated changes to the code. 154b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.visitCodeAttribute(clazz, method, codeAttribute); 155b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 156b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 157b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 158b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Implementations for InstructionVisitor. 159b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 160b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitSimpleInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, SimpleInstruction simpleInstruction) 161b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 162b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato switch (simpleInstruction.opcode) 163b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 164b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IALOAD: 165b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_BALOAD: 166b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_CALOAD: 167b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_SALOAD: 168b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IADD: 169b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ISUB: 170b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IMUL: 171b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IDIV: 172b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IREM: 173b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_INEG: 174b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ISHL: 175b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ISHR: 176b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IUSHR: 177b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IAND: 178b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IOR: 179b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_IXOR: 180b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_L2I: 181b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_F2I: 182b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_D2I: 183b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_I2B: 184b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_I2C: 185b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_I2S: 1862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom case InstructionConstants.OP_ARRAYLENGTH: 187b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceIntegerPushInstruction(clazz, offset, simpleInstruction); 188b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 189b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 190b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LALOAD: 191b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LADD: 192b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LSUB: 193b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LMUL: 194b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LDIV: 195b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LREM: 196b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LNEG: 197b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LSHL: 198b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LSHR: 199b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LUSHR: 200b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LAND: 201b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LOR: 202b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LXOR: 203b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_I2L: 204b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_F2L: 205b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_D2L: 206b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceLongPushInstruction(clazz, offset, simpleInstruction); 207b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_FALOAD: 210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_FADD: 211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_FSUB: 212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_FMUL: 213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_FDIV: 214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_FREM: 215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_FNEG: 216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_I2F: 217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_L2F: 218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_D2F: 219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceFloatPushInstruction(clazz, offset, simpleInstruction); 220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_DALOAD: 223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_DADD: 224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_DSUB: 225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_DMUL: 226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_DDIV: 227b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_DREM: 228b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_DNEG: 229b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_I2D: 230b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_L2D: 231b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_F2D: 232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceDoublePushInstruction(clazz, offset, simpleInstruction); 233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_AALOAD: 236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceReferencePushInstruction(clazz, offset, simpleInstruction); 237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitVariableInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, VariableInstruction variableInstruction) 243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int variableIndex = variableInstruction.variableIndex; 245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato switch (variableInstruction.opcode) 247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ILOAD: 249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ILOAD_0: 250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ILOAD_1: 251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ILOAD_2: 252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ILOAD_3: 253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceIntegerPushInstruction(clazz, offset, variableInstruction, variableIndex); 254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LLOAD: 257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LLOAD_0: 258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LLOAD_1: 259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LLOAD_2: 260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_LLOAD_3: 261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceLongPushInstruction(clazz, offset, variableInstruction, variableIndex); 262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_FLOAD: 265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_FLOAD_0: 266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_FLOAD_1: 267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_FLOAD_2: 268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_FLOAD_3: 269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceFloatPushInstruction(clazz, offset, variableInstruction, variableIndex); 270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_DLOAD: 273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_DLOAD_0: 274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_DLOAD_1: 275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_DLOAD_2: 276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_DLOAD_3: 277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceDoublePushInstruction(clazz, offset, variableInstruction, variableIndex); 278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ALOAD: 281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ALOAD_0: 282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ALOAD_1: 283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ALOAD_2: 284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ALOAD_3: 285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceReferencePushInstruction(clazz, offset, variableInstruction); 286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ASTORE: 289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ASTORE_0: 290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ASTORE_1: 291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ASTORE_2: 292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_ASTORE_3: 293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato deleteReferencePopInstruction(clazz, offset, variableInstruction); 294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_RET: 297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceBranchInstruction(clazz, offset, variableInstruction); 298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitConstantInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, ConstantInstruction constantInstruction) 304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato switch (constantInstruction.opcode) 306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_GETSTATIC: 308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_GETFIELD: 309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceAnyPushInstruction(clazz, offset, constantInstruction); 310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_INVOKEVIRTUAL: 313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_INVOKESPECIAL: 314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_INVOKESTATIC: 315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_INVOKEINTERFACE: 316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (constantInstruction.stackPushCount(clazz) > 0 && 317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato !sideEffectInstructionChecker.hasSideEffects(clazz, 318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato method, 319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttribute, 320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato constantInstruction)) 322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceAnyPushInstruction(clazz, offset, constantInstruction); 324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 325b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 326b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 327b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 328b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_CHECKCAST: 329b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceReferencePushInstruction(clazz, offset, constantInstruction); 330b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 331b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 332b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 333b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 334b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 335b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato public void visitBranchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, BranchInstruction branchInstruction) 336b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 337b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato switch (branchInstruction.opcode) 338b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 339b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_GOTO: 340b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_GOTO_W: 341b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Don't replace unconditional branches. 342b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 343b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 344b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_JSR: 345b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case InstructionConstants.OP_JSR_W: 346b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceJsrInstruction(clazz, offset, branchInstruction); 347b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 348b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 349b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato default: 350b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceBranchInstruction(clazz, offset, branchInstruction); 351b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 352b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 353b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 354b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 355b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 3562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom public void visitTableSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, TableSwitchInstruction tableSwitchInstruction) 357b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 358b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // First try to simplify it to a simple branch. 3592270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replaceBranchInstruction(clazz, offset, tableSwitchInstruction); 360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 3612270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Otherwise try to simplify simple enum switches. 362b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (!codeAttributeEditor.isModified(offset)) 363b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 3642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replaceSimpleEnumSwitchInstruction(clazz, 3652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom codeAttribute, 3662270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom offset, 3672270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction); 3682270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 3692270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Otherwise make sure all branch targets are valid. 3702270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (!codeAttributeEditor.isModified(offset)) 3712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 3722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom cleanUpSwitchInstruction(clazz, offset, tableSwitchInstruction); 3732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 3742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom trimSwitchInstruction(clazz, offset, tableSwitchInstruction); 3752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 3762270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 3772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 3782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 3792270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 3802270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom public void visitLookUpSwitchInstruction(Clazz clazz, Method method, CodeAttribute codeAttribute, int offset, LookUpSwitchInstruction lookUpSwitchInstruction) 3812270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 3822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // First try to simplify it to a simple branch. 3832270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replaceBranchInstruction(clazz, offset, lookUpSwitchInstruction); 3842270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 3852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Otherwise try to simplify simple enum switches. 3862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (!codeAttributeEditor.isModified(offset)) 3872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 3882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replaceSimpleEnumSwitchInstruction(clazz, 3892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom codeAttribute, 3902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom offset, 3912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom lookUpSwitchInstruction); 3922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 3932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Otherwise make sure all branch targets are valid. 3942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (!codeAttributeEditor.isModified(offset)) 3952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 3962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom cleanUpSwitchInstruction(clazz, offset, lookUpSwitchInstruction); 3972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 3982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom trimSwitchInstruction(clazz, offset, lookUpSwitchInstruction); 3992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 400b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 401b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 402b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 403b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 404b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Small utility methods. 405b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 406b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 407b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the push instruction at the given offset by a simpler push 408b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * instruction, if possible. 409b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 410b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceAnyPushInstruction(Clazz clazz, 411b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 412b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction) 413b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 414b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0); 415b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (pushedValue.isParticular()) 416b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 417b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato switch (pushedValue.computationalType()) 418b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 419b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case Value.TYPE_INTEGER: 420b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceIntegerPushInstruction(clazz, offset, instruction); 421b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 422b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case Value.TYPE_LONG: 423b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceLongPushInstruction(clazz, offset, instruction); 424b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 425b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case Value.TYPE_FLOAT: 426b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceFloatPushInstruction(clazz, offset, instruction); 427b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 428b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case Value.TYPE_DOUBLE: 429b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceDoublePushInstruction(clazz, offset, instruction); 430b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 431b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case Value.TYPE_REFERENCE: 432b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceReferencePushInstruction(clazz, offset, instruction); 433b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 434b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 435b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 436b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 437b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 438b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 439b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 440b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the integer pushing instruction at the given offset by a simpler 441b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * push instruction, if possible. 442b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 443b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceIntegerPushInstruction(Clazz clazz, 444b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 445b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction) 446b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 447b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceIntegerPushInstruction(clazz, 448b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 449b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 450b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato partialEvaluator.getVariablesBefore(offset).size()); 451b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 452b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 453b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 454b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 455b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the integer pushing instruction at the given offset by a simpler 456b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * push instruction, if possible. 457b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 458b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceIntegerPushInstruction(Clazz clazz, 459b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 460b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction, 461b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int maxVariableIndex) 462b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 463b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0); 464b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (pushedValue.isParticular()) 465b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 466b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Push a constant instead. 467b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int value = pushedValue.integerValue().value(); 468b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if ((short)value == value) 469b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 470b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceConstantPushInstruction(clazz, 471b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 472b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 473b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionConstants.OP_SIPUSH, 474b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato value); 475b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 476b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else 477b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 478b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ConstantPoolEditor constantPoolEditor = 479b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ConstantPoolEditor((ProgramClass)clazz); 480b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 481b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = 482b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ConstantInstruction(InstructionConstants.OP_LDC, 483b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang constantPoolEditor.addIntegerConstant(value)); 484b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 485b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceInstruction(clazz, offset, instruction, replacementInstruction); 486b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 487b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 488b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else if (pushedValue.isSpecific()) 489b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 490b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Load an equivalent lower-numbered variable instead, if any. 491b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato TracedVariables variables = partialEvaluator.getVariablesBefore(offset); 492b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++) 493b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 494b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (pushedValue.equals(variables.load(variableIndex))) 495b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 496b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceVariablePushInstruction(clazz, 497b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 498b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 499b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionConstants.OP_ILOAD, 500b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato variableIndex); 501b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang break; 502b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 503b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 504b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 505b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 506b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 507b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 508b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 509b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the long pushing instruction at the given offset by a simpler 510b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * push instruction, if possible. 511b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 512b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceLongPushInstruction(Clazz clazz, 513b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 514b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction) 515b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 516b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceLongPushInstruction(clazz, 517b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 518b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 519b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato partialEvaluator.getVariablesBefore(offset).size()); 520b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 521b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 522b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 523b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 524b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the long pushing instruction at the given offset by a simpler 525b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * push instruction, if possible. 526b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 527b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceLongPushInstruction(Clazz clazz, 528b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 529b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction, 530b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int maxVariableIndex) 531b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 532b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0); 533b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (pushedValue.isParticular()) 534b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 535b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Push a constant instead. 536b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato long value = pushedValue.longValue().value(); 537b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (value == 0L || 538b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato value == 1L) 539b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 540b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceConstantPushInstruction(clazz, 541b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 542b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 543b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionConstants.OP_LCONST_0, 544b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (int)value); 545b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 546b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else 547b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 548b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ConstantPoolEditor constantPoolEditor = 549b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ConstantPoolEditor((ProgramClass)clazz); 550b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 551b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = 552b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ConstantInstruction(InstructionConstants.OP_LDC2_W, 553b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang constantPoolEditor.addLongConstant(value)); 554b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 555b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceInstruction(clazz, offset, instruction, replacementInstruction); 556b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 557b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 558b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else if (pushedValue.isSpecific()) 559b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 560b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Load an equivalent lower-numbered variable instead, if any. 561b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato TracedVariables variables = partialEvaluator.getVariablesBefore(offset); 562b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++) 563b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 564b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Note that we have to check the second part as well. 565b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (pushedValue.equals(variables.load(variableIndex)) && 566b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang variables.load(variableIndex + 1) != null && 567b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP) 568b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 569b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceVariablePushInstruction(clazz, 570b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 571b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 572b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionConstants.OP_LLOAD, 573b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato variableIndex); 574b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 575b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 576b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 577b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 578b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 579b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 580b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 581b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the float pushing instruction at the given offset by a simpler 582b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * push instruction, if possible. 583b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 584b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceFloatPushInstruction(Clazz clazz, 585b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 586b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction) 587b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 588b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceFloatPushInstruction(clazz, 589b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 590b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 591b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato partialEvaluator.getVariablesBefore(offset).size()); 592b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 593b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 594b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 595b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 596b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the float pushing instruction at the given offset by a simpler 597b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * push instruction, if possible. 598b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 599b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceFloatPushInstruction(Clazz clazz, 600b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 601b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction, 602b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int maxVariableIndex) 603b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 604b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0); 605b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (pushedValue.isParticular()) 606b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 607b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Push a constant instead. 608b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Make sure to distinguish between +0.0 and -0.0. 609b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato float value = pushedValue.floatValue().value(); 610b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (value == 0.0f && Float.floatToIntBits(value) == POS_ZERO_FLOAT_BITS || 611b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang value == 1.0f || 612b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang value == 2.0f) 613b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 614b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceConstantPushInstruction(clazz, 615b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 616b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 617b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionConstants.OP_FCONST_0, 618b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (int)value); 619b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 620b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else 621b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 622b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ConstantPoolEditor constantPoolEditor = 623b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ConstantPoolEditor((ProgramClass)clazz); 624b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 625b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = 626b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ConstantInstruction(InstructionConstants.OP_LDC, 627b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang constantPoolEditor.addFloatConstant(value)); 628b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 629b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceInstruction(clazz, offset, instruction, replacementInstruction); 630b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 631b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 632b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else if (pushedValue.isSpecific()) 633b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 634b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Load an equivalent lower-numbered variable instead, if any. 635b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato TracedVariables variables = partialEvaluator.getVariablesBefore(offset); 636b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++) 637b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 638b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (pushedValue.equals(variables.load(variableIndex))) 639b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 640b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceVariablePushInstruction(clazz, 641b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 642b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 643b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionConstants.OP_FLOAD, 644b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato variableIndex); 645b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 646b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 647b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 648b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 649b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 650b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 651b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 652b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the double pushing instruction at the given offset by a simpler 653b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * push instruction, if possible. 654b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 655b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceDoublePushInstruction(Clazz clazz, 656b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 657b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction) 658b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 659b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceDoublePushInstruction(clazz, 660b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 661b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 662b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato partialEvaluator.getVariablesBefore(offset).size()); 663b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 664b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 665b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 666b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 667b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the double pushing instruction at the given offset by a simpler 668b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * push instruction, if possible. 669b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 670b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceDoublePushInstruction(Clazz clazz, 671b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 672b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction, 673b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int maxVariableIndex) 674b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 675b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0); 676b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (pushedValue.isParticular()) 677b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 678b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Push a constant instead. 679b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Make sure to distinguish between +0.0 and -0.0. 680b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato double value = pushedValue.doubleValue().value(); 681b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (value == 0.0 && Double.doubleToLongBits(value) == POS_ZERO_DOUBLE_BITS || 682b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato value == 1.0) 683b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 684b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceConstantPushInstruction(clazz, 685b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 686b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 687b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionConstants.OP_DCONST_0, 688b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (int)value); 689b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 690b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else 691b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 692b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato ConstantPoolEditor constantPoolEditor = 693b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ConstantPoolEditor((ProgramClass)clazz); 694b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 695b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = 696b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new ConstantInstruction(InstructionConstants.OP_LDC2_W, 697b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang constantPoolEditor.addDoubleConstant(value)); 698b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 699b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceInstruction(clazz, offset, instruction, replacementInstruction); 700b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 701b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 702b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else if (pushedValue.isSpecific()) 703b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 704b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Load an equivalent lower-numbered variable instead, if any. 705b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato TracedVariables variables = partialEvaluator.getVariablesBefore(offset); 706b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int variableIndex = 0; variableIndex < maxVariableIndex; variableIndex++) 707b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 708b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang // Note that we have to check the second part as well. 709b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang if (pushedValue.equals(variables.load(variableIndex)) && 710b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang variables.load(variableIndex + 1) != null && 711b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang variables.load(variableIndex + 1).computationalType() == Value.TYPE_TOP) 712b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 713b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceVariablePushInstruction(clazz, 714b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 715b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 716b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionConstants.OP_DLOAD, 717b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato variableIndex); 718b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 719b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 720b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 721b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 722b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 723b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 724b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 725b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the reference pushing instruction at the given offset by a 726b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * simpler push instruction, if possible. 727b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 728b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceReferencePushInstruction(Clazz clazz, 729b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 730b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction) 731b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 732b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Value pushedValue = partialEvaluator.getStackAfter(offset).getTop(0); 733b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (pushedValue.isParticular()) 734b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 735b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // A reference value can only be specific if it is null. 736b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceConstantPushInstruction(clazz, 737b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset, 738b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction, 739b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionConstants.OP_ACONST_NULL, 740b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 0); 741b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 742b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 743b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 744b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 745b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 746b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the instruction at a given offset by a given push instruction 747b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of a constant. 748b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 749b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceConstantPushInstruction(Clazz clazz, 750b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 751b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction, 752b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato byte replacementOpcode, 753b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int value) 754b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 755b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = 756b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new SimpleInstruction(replacementOpcode, value); 757b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 758b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceInstruction(clazz, offset, instruction, replacementInstruction); 759b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 760b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 761b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 762b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 763b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the instruction at a given offset by a given push instruction 764b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * of a variable. 765b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 766b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceVariablePushInstruction(Clazz clazz, 767b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 768b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction, 769b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato byte replacementOpcode, 770b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int variableIndex) 771b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 772b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = 773b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new VariableInstruction(replacementOpcode, variableIndex); 774b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 775b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceInstruction(clazz, offset, instruction, replacementInstruction); 776b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 777b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 778b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 779b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 780b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the given 'jsr' instruction by a simpler branch instruction, 781b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * if it jumps to a subroutine that doesn't return or a subroutine that 782b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * is only called from one place. 783b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 784b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceJsrInstruction(Clazz clazz, 785b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 786b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato BranchInstruction branchInstruction) 787b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 788b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Is the subroutine ever returning? 789b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int subroutineStart = offset + branchInstruction.branchOffset; 790b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (!partialEvaluator.isSubroutineReturning(subroutineStart) || 791b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato partialEvaluator.branchOrigins(subroutineStart).instructionOffsetCount() == 1) 792b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 793b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // All 'jsr' instructions to this subroutine can be replaced 794b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // by unconditional branch instructions. 795b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceBranchInstruction(clazz, offset, branchInstruction); 796b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 797b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else if (!partialEvaluator.isTraced(offset + branchInstruction.length(offset))) 798b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 799b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // We have to make sure the instruction after this 'jsr' 800b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // instruction is valid, even if it is never reached. 801b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceByInfiniteLoop(clazz, offset + branchInstruction.length(offset), branchInstruction); 802b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 803b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 804b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 805b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 806b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 807b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Deletes the reference popping instruction at the given offset, if 808b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * it is at the start of a subroutine that doesn't return or a subroutine 809b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * that is only called from one place. 810b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 811b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void deleteReferencePopInstruction(Clazz clazz, 812b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 813b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction) 814b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 815b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (partialEvaluator.isSubroutineStart(offset) && 816b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato (!partialEvaluator.isSubroutineReturning(offset) || 817b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato partialEvaluator.branchOrigins(offset).instructionOffsetCount() == 1)) 818b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 819b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) System.out.println(" Deleting store of subroutine return address "+instruction.toString(offset)); 820b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 821b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // A reference value can only be specific if it is null. 822b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.deleteInstruction(offset); 823b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 824b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 825b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 826b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 827b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 828b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Deletes the given branch instruction, or replaces it by a simpler branch 829b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * instruction, if possible. 830b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 831b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceBranchInstruction(Clazz clazz, 832b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 833b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction) 834b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 835b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset); 836b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 837b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Is there exactly one branch target (not from a goto or jsr)? 838b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (branchTargets != null && 839b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato branchTargets.instructionOffsetCount() == 1) 840b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 841b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Is it branching to the next instruction? 842b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int branchOffset = branchTargets.instructionOffset(0) - offset; 843b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (branchOffset == instruction.length(offset)) 844b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 845b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) System.out.println(" Ignoring zero branch instruction at ["+offset+"]"); 846b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 847b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato else 848b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 849b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Replace the branch instruction by a simple branch instruction. 850b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = 851b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang new BranchInstruction(InstructionConstants.OP_GOTO, 852b9cc48a43ed984587c939d02fba5316bf5c0df6eYing Wang branchOffset); 853b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 854b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceInstruction(clazz, offset, instruction, replacementInstruction); 855b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 856b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 857b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 858b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 859b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 860b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 8612270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Replaces the given table switch instruction, if it is based on the value 8622270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * of a fixed array. This is typical for switches on simple enums. 8632270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom */ 8642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private void replaceSimpleEnumSwitchInstruction(Clazz clazz, 8652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom CodeAttribute codeAttribute, 8662270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int offset, 8672270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom TableSwitchInstruction tableSwitchInstruction) 8682270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 8692270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Check if the switch instruction is consuming a single value loaded 8702270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // from a fully specified array. 8712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom InstructionOffsetValue producerOffsets = 8722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom partialEvaluator.getStackBefore(offset).getTopProducerValue(0).instructionOffsetValue(); 8732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 8742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (producerOffsets.instructionOffsetCount() == 1) 8752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 8762270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int producerOffset = producerOffsets.instructionOffset(0); 8772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 8782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (codeAttribute.code[producerOffset] == InstructionConstants.OP_IALOAD && 8792270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom !codeAttributeEditor.isModified(producerOffset)) 8802270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 8812270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ReferenceValue referenceValue = 8822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom partialEvaluator.getStackBefore(producerOffset).getTop(1).referenceValue(); 8832270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 8842270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (referenceValue.isParticular()) 8852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 8862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Simplify the entire construct. 8872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replaceSimpleEnumSwitchInstruction(clazz, 8882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom codeAttribute, 8892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom producerOffset, 8902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom offset, 8912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction, 8922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom referenceValue); 8932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 8942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 8952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 8962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 8972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 8982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 8992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom /** 9002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Replaces the given table switch instruction that is based on a value of 9012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * the given fixed array. 9022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom */ 9032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private void replaceSimpleEnumSwitchInstruction(Clazz clazz, 9042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom CodeAttribute codeAttribute, 9052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int loadOffset, 9062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int switchOffset, 9072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom TableSwitchInstruction tableSwitchInstruction, 9082270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ReferenceValue mappingValue) 9092270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 9102270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ValueFactory valueFactory = new ParticularValueFactory(); 9112270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9122270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Transform the jump offsets. 9132270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] jumpOffsets = tableSwitchInstruction.jumpOffsets; 9142270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] newJumpOffsets = new int[mappingValue.arrayLength(valueFactory).value()]; 9152270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9162270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom for (int index = 0; index < newJumpOffsets.length; index++) 9172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 9182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int switchCase = 9192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom mappingValue.integerArrayLoad(valueFactory.createIntegerValue( 9202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom index), 9212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom valueFactory).value(); 9222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newJumpOffsets[index] = 9242270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom switchCase >= tableSwitchInstruction.lowCase && 9252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom switchCase <= tableSwitchInstruction.highCase ? 9262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom jumpOffsets[switchCase - tableSwitchInstruction.lowCase] : 9272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction.defaultOffset; 9282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 9292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Update the instruction. 9312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction.lowCase = 0; 9322270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction.highCase = newJumpOffsets.length - 1; 9332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction.jumpOffsets = newJumpOffsets; 9342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Replace the original one with the new version. 9362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replaceSimpleEnumSwitchInstruction(clazz, 9372270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom loadOffset, 9382270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom switchOffset, 9392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction); 9402270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9412270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom cleanUpSwitchInstruction(clazz, switchOffset, tableSwitchInstruction); 9422270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9432270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom trimSwitchInstruction(clazz, switchOffset, tableSwitchInstruction); 9442270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 9452270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9462270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9472270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom /** 9482270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Replaces the given look up switch instruction, if it is based on the 9492270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * value of a fixed array. This is typical for switches on simple enums. 9502270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom */ 9512270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private void replaceSimpleEnumSwitchInstruction(Clazz clazz, 9522270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom CodeAttribute codeAttribute, 9532270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int offset, 9542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom LookUpSwitchInstruction lookupSwitchInstruction) 9552270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 9562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Check if the switch instruction is consuming a single value loaded 9572270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // from a fully specified array. 9582270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom InstructionOffsetValue producerOffsets = 9592270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom partialEvaluator.getStackBefore(offset).getTopProducerValue(0).instructionOffsetValue(); 9602270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9612270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (producerOffsets.instructionOffsetCount() == 1) 9622270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 9632270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int producerOffset = producerOffsets.instructionOffset(0); 9642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (codeAttribute.code[producerOffset] == InstructionConstants.OP_IALOAD && 9662270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom !codeAttributeEditor.isModified(producerOffset)) 9672270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 9682270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ReferenceValue referenceValue = 9692270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom partialEvaluator.getStackBefore(producerOffset).getTop(1).referenceValue(); 9702270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (referenceValue.isParticular()) 9722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 9732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Simplify the entire construct. 9742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replaceSimpleEnumSwitchInstruction(clazz, 9752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom codeAttribute, 9762270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom producerOffset, 9772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom offset, 9782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom lookupSwitchInstruction, 9792270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom referenceValue); 9802270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 9812270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 9822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 9832270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 9842270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom /** 9872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Replaces the given look up switch instruction that is based on a value of 9882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * the given fixed array. This is typical for switches on simple enums. 9892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom */ 9902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private void replaceSimpleEnumSwitchInstruction(Clazz clazz, 9912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom CodeAttribute codeAttribute, 9922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int loadOffset, 9932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int switchOffset, 9942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom LookUpSwitchInstruction lookupSwitchInstruction, 9952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ReferenceValue mappingValue) 9962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 9972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom ValueFactory valueFactory = new ParticularValueFactory(); 9982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 9992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Transform the jump offsets. 10002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] cases = lookupSwitchInstruction.cases; 10012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] jumpOffsets = lookupSwitchInstruction.jumpOffsets; 10022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] newJumpOffsets = new int[mappingValue.arrayLength(valueFactory).value()]; 10032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom for (int index = 0; index < newJumpOffsets.length; index++) 10052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 10062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int switchCase = 10072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom mappingValue.integerArrayLoad(valueFactory.createIntegerValue(index), 10082270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom valueFactory).value(); 10092270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10102270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int caseIndex = Arrays.binarySearch(cases, switchCase); 10112270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10122270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newJumpOffsets[index] = caseIndex >= 0 ? 10132270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom jumpOffsets[caseIndex] : 10142270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom lookupSwitchInstruction.defaultOffset; 10152270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 10162270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Replace the original lookup switch with a table switch. 10182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom TableSwitchInstruction replacementSwitchInstruction = 10192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new TableSwitchInstruction(InstructionConstants.OP_TABLESWITCH, 10202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom lookupSwitchInstruction.defaultOffset, 10212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 0, 10222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newJumpOffsets.length - 1, 10232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newJumpOffsets); 10242270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replaceSimpleEnumSwitchInstruction(clazz, 10262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom loadOffset, 10272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom switchOffset, 10282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replacementSwitchInstruction); 10292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom cleanUpSwitchInstruction(clazz, switchOffset, replacementSwitchInstruction); 10312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10322270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom trimSwitchInstruction(clazz, switchOffset, replacementSwitchInstruction); 10332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 10342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom /** 1037b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Makes sure all branch targets of the given switch instruction are valid. 1038b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 10392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private void cleanUpSwitchInstruction(Clazz clazz, 1040b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 1041b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato SwitchInstruction switchInstruction) 1042b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1043b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Get the actual branch targets. 1044b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato InstructionOffsetValue branchTargets = partialEvaluator.branchTargets(offset); 1045b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1046b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Get an offset that can serve as a valid default offset. 1047b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int defaultOffset = 1048b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato branchTargets.instructionOffset(branchTargets.instructionOffsetCount()-1) - 1049b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato offset; 1050b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1051b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = null; 1052b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1053b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Check the jump offsets. 1054b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int[] jumpOffsets = switchInstruction.jumpOffsets; 1055b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int index = 0; index < jumpOffsets.length; index++) 1056b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1057b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (!branchTargets.contains(offset + jumpOffsets[index])) 1058b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1059b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Replace the unused offset. 1060b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato jumpOffsets[index] = defaultOffset; 1061b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1062b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Remember to replace the instruction. 1063b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replacementInstruction = switchInstruction; 1064b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1065b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1066b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1067b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Check the default offset. 1068b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (!branchTargets.contains(offset + switchInstruction.defaultOffset)) 1069b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1070b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Replace the unused offset. 1071b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato switchInstruction.defaultOffset = defaultOffset; 1072b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1073b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Remember to replace the instruction. 1074b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replacementInstruction = switchInstruction; 1075b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1076b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1077b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (replacementInstruction != null) 1078b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1079b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replaceInstruction(clazz, offset, switchInstruction, replacementInstruction); 1080b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1081b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1082b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1083b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1084b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 10852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Trims redundant offsets from the given switch instruction. 10862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom */ 10872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private void trimSwitchInstruction(Clazz clazz, 10882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int offset, 10892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom TableSwitchInstruction tableSwitchInstruction) 10902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 10912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Get an offset that can serve as a valid default offset. 10922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int defaultOffset = tableSwitchInstruction.defaultOffset; 10932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] jumpOffsets = tableSwitchInstruction.jumpOffsets; 10942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int length = jumpOffsets.length; 10952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 10962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Find the lowest index with a non-default jump offset. 10972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int lowIndex = 0; 10982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom while (lowIndex < length && 10992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom jumpOffsets[lowIndex] == defaultOffset) 11002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom lowIndex++; 11022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 11032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Find the highest index with a non-default jump offset. 11052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int highIndex = length - 1; 11062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom while (highIndex >= 0 && 11072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom jumpOffsets[highIndex] == defaultOffset) 11082270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11092270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom highIndex--; 11102270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 11112270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11122270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Can we use a shorter array? 11132270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int newLength = highIndex - lowIndex + 1; 11142270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (newLength < length) 11152270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11162270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (newLength <= 0) 11172270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11182270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Replace the switch instruction by a simple branch instruction. 11192270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom Instruction replacementInstruction = 11202270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new BranchInstruction(InstructionConstants.OP_GOTO, 11212270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom defaultOffset); 11222270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11232270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replaceInstruction(clazz, offset, tableSwitchInstruction, 11242270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replacementInstruction); 11252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 11262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom else 11272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Trim the array. 11292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] newJumpOffsets = new int[newLength]; 11302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom System.arraycopy(jumpOffsets, lowIndex, newJumpOffsets, 0, newLength); 11322270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction.jumpOffsets = newJumpOffsets; 11342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction.lowCase += lowIndex; 11352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction.highCase -= length - newLength - lowIndex; 11362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11372270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replaceInstruction(clazz, offset, tableSwitchInstruction, 11382270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom tableSwitchInstruction); 11392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 11402270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 11412270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 11422270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11432270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11442270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom /** 11452270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Trims redundant offsets from the given switch instruction. 11462270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom */ 11472270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private void trimSwitchInstruction(Clazz clazz, 11482270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int offset, 11492270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom LookUpSwitchInstruction lookUpSwitchInstruction) 11502270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11512270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Get an offset that can serve as a valid default offset. 11522270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int defaultOffset = lookUpSwitchInstruction.defaultOffset; 11532270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] jumpOffsets = lookUpSwitchInstruction.jumpOffsets; 11542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int length = jumpOffsets.length; 11552270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int newLength = length; 11562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11572270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Count the default jump offsets. 11582270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom for (int index = 0; index < length; index++) 11592270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11602270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (jumpOffsets[index] == defaultOffset) 11612270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11622270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newLength--; 11632270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 11642270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 11652270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11662270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Can we use shorter arrays? 11672270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (newLength < length) 11682270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11692270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (newLength <= 0) 11702270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11712270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Replace the switch instruction by a simple branch instruction. 11722270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom Instruction replacementInstruction = 11732270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new BranchInstruction(InstructionConstants.OP_GOTO, 11742270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom defaultOffset); 11752270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11762270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replaceInstruction(clazz, offset, lookUpSwitchInstruction, 11772270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replacementInstruction); 11782270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 11792270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom else 11802270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11812270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Remove redundant entries from the arrays. 11822270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] cases = lookUpSwitchInstruction.cases; 11832270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] newJumpOffsets = new int[newLength]; 11842270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int[] newCases = new int[newLength]; 11852270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11862270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int newIndex = 0; 11872270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11882270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom for (int index = 0; index < length; index++) 11892270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11902270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (jumpOffsets[index] != defaultOffset) 11912270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 11922270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newJumpOffsets[newIndex] = jumpOffsets[index]; 11932270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom newCases[newIndex++] = cases[index]; 11942270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 11952270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 11962270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 11972270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom lookUpSwitchInstruction.jumpOffsets = newJumpOffsets; 11982270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom lookUpSwitchInstruction.cases = newCases; 11992270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 12002270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replaceInstruction(clazz, offset, lookUpSwitchInstruction, 12012270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom lookUpSwitchInstruction); 12022270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 12032270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 12042270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 12052270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 12062270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 12072270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom /** 1208b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the given instruction by an infinite loop. 1209b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 1210b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceByInfiniteLoop(Clazz clazz, 1211b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 1212b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction) 1213b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1214b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Replace the instruction by an infinite loop. 1215b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction = 1216b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new BranchInstruction(InstructionConstants.OP_GOTO, 0); 1217b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1218b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) System.out.println(" Replacing unreachable instruction by infinite loop "+replacementInstruction.toString(offset)); 1219b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1220b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.replaceInstruction(offset, replacementInstruction); 1221b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1222b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit the instruction, if required. 1223b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (extraInstructionVisitor != null) 1224b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1225b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Note: we're not passing the right arguments for now, knowing that 1226b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // they aren't used anyway. 12272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom instruction.accept(clazz, 12282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom null, 12292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom null, 12302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom offset, 12312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom extraInstructionVisitor); 1232b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1233b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1234b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1235b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1236b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 1237b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Replaces the instruction at a given offset by a given push instruction. 1238b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 1239b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void replaceInstruction(Clazz clazz, 1240b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int offset, 1241b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction instruction, 1242b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction replacementInstruction) 1243b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1244b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Pop unneeded stack entries if necessary. 1245b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato int popCount = 1246b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction.stackPopCount(clazz) - 1247b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato replacementInstruction.stackPopCount(clazz); 1248b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1249b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato insertPopInstructions(offset, popCount); 1250b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1251b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (DEBUG) System.out.println(" Replacing instruction "+instruction.toString(offset)+" -> "+replacementInstruction.toString()+(popCount == 0 ? "" : " ("+popCount+" pops)")); 1252b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1253b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.replaceInstruction(offset, replacementInstruction); 1254b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1255b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Visit the instruction, if required. 1256b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (extraInstructionVisitor != null) 1257b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1258b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Note: we're not passing the right arguments for now, knowing that 1259b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // they aren't used anyway. 1260b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato instruction.accept(clazz, null, null, offset, extraInstructionVisitor); 1261b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1262b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1263b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1264b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1265b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato /** 1266b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * Pops the given number of stack entries before the instruction at the 1267b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato * given offset. 1268b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato */ 1269b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato private void insertPopInstructions(int offset, int popCount) 1270b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1271b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato switch (popCount) 1272b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1273b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case 0: 1274b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1275b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 1276b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1277b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case 1: 1278b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1279b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Insert a single pop instruction. 1280b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction popInstruction = 1281b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimpleInstruction(InstructionConstants.OP_POP); 1282b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1283b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.insertBeforeInstruction(offset, 1284b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato popInstruction); 1285b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 1286b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1287b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato case 2: 1288b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1289b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Insert a single pop2 instruction. 1290b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction popInstruction = 1291b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimpleInstruction(InstructionConstants.OP_POP2); 1292b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1293b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.insertBeforeInstruction(offset, 1294b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato popInstruction); 1295b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 1296b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1297b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato default: 1298b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1299b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato // Insert the specified number of pop instructions. 1300b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction[] popInstructions = 1301b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new Instruction[popCount / 2 + popCount % 2]; 1302b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1303b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato Instruction popInstruction = 1304b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimpleInstruction(InstructionConstants.OP_POP2); 1305b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1306b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato for (int index = 0; index < popCount / 2; index++) 1307b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1308b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato popInstructions[index] = popInstruction; 1309b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1310b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1311b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato if (popCount % 2 == 1) 1312b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato { 1313b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato popInstruction = 1314b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato new SimpleInstruction(InstructionConstants.OP_POP); 1315b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1316b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato popInstructions[popCount / 2] = popInstruction; 1317b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1318b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato 1319b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato codeAttributeEditor.insertBeforeInstruction(offset, 1320b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato popInstructions); 1321b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato break; 1322b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1323b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 1324b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato } 13252270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 13262270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 13272270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom /** 13282270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * Replaces the simple enum switch instructions at a given offsets by a 13292270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom * given replacement instruction. 13302270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom */ 13312270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom private void replaceSimpleEnumSwitchInstruction(Clazz clazz, 13322270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int loadOffset, 13332270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom int switchOffset, 13342270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom SwitchInstruction replacementSwitchInstruction) 13352270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 13362270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (DEBUG) System.out.println(" Replacing switch instruction at ["+switchOffset+"] -> ["+loadOffset+"] swap + pop, "+replacementSwitchInstruction.toString(switchOffset)+")"); 13372270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 13382270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Remove the array load instruction. 13392270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom codeAttributeEditor.replaceInstruction(loadOffset, new Instruction[] 13402270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 13412270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new SimpleInstruction(InstructionConstants.OP_SWAP), 13422270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom new SimpleInstruction(InstructionConstants.OP_POP), 13432270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom }); 13442270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 13452270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Replace the switch instruction. 13462270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom codeAttributeEditor.replaceInstruction(switchOffset, replacementSwitchInstruction); 13472270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom 13482270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Visit the instruction, if required. 13492270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom if (extraInstructionVisitor != null) 13502270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom { 13512270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // Note: we're not passing the right arguments for now, knowing that 13522270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom // they aren't used anyway. 13532270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom replacementSwitchInstruction.accept(clazz, 13542270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom null, 13552270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom null, 13562270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom switchOffset, 13572270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom extraInstructionVisitor); 13582270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 13592270795fbe0b277bfd49f40950ecaa78583175ccBrian Carlstrom } 1360b72c5c2e5482cf10117b2b25f642f7616b2326c3Joe Onorato} 1361